/drivers/devman/acpica/events/evevent.c |
---|
8,7 → 8,7 |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
180,54 → 180,6 |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvInstallFadtGpes |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Completes initialization of the FADT-defined GPE blocks |
* (0 and 1). This causes the _PRW methods to be run, so the HW |
* must be fully initialized at this point, including global lock |
* support. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvInstallFadtGpes ( |
void) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvInstallFadtGpes); |
/* Namespace must be locked */ |
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
if (ACPI_FAILURE (Status)) |
{ |
return (Status); |
} |
/* FADT GPE Block 0 */ |
(void) AcpiEvInitializeGpeBlock ( |
AcpiGbl_FadtGpeDevice, AcpiGbl_GpeFadtBlocks[0]); |
/* FADT GPE Block 1 */ |
(void) AcpiEvInitializeGpeBlock ( |
AcpiGbl_FadtGpeDevice, AcpiGbl_GpeFadtBlocks[1]); |
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
return_ACPI_STATUS (AE_OK); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvInstallXruptHandlers |
* |
* PARAMETERS: None |
366,9 → 318,17 |
if ((FixedStatus & AcpiGbl_FixedEventInfo[i].StatusBitMask) && |
(FixedEnable & AcpiGbl_FixedEventInfo[i].EnableBitMask)) |
{ |
/* Found an active (signalled) event */ |
/* |
* Found an active (signalled) event. Invoke global event |
* handler if present. |
*/ |
AcpiFixedEventCount[i]++; |
if (AcpiGbl_GlobalEventHandler) |
{ |
AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_FIXED, NULL, |
i, AcpiGbl_GlobalEventHandlerContext); |
} |
AcpiFixedEventCount[i]++; |
IntStatus |= AcpiEvFixedEventDispatch (i); |
} |
} |
/drivers/devman/acpica/events/evglock.c |
---|
0,0 → 1,439 |
/****************************************************************************** |
* |
* Module Name: evglock - Global Lock support |
* |
*****************************************************************************/ |
/****************************************************************************** |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
* |
* 2.1. This is your license from Intel Corp. under its intellectual property |
* rights. You may have additional license terms from the party that provided |
* you this software, covering your right to use that party's intellectual |
* property rights. |
* |
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a |
* copy of the source code appearing in this file ("Covered Code") an |
* irrevocable, perpetual, worldwide license under Intel's copyrights in the |
* base code distributed originally by Intel ("Original Intel Code") to copy, |
* make derivatives, distribute, use and display any portion of the Covered |
* Code in any form, with the right to sublicense such rights; and |
* |
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent |
* license (with the right to sublicense), under only those claims of Intel |
* patents that are infringed by the Original Intel Code, to make, use, sell, |
* offer to sell, and import the Covered Code and derivative works thereof |
* solely to the minimum extent necessary to exercise the above copyright |
* license, and in no event shall the patent license extend to any additions |
* to or modifications of the Original Intel Code. No other license or right |
* is granted directly or by implication, estoppel or otherwise; |
* |
* The above copyright and patent license is granted only if the following |
* conditions are met: |
* |
* 3. Conditions |
* |
* 3.1. Redistribution of Source with Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification with rights to further distribute source must include |
* the above Copyright Notice, the above License, this list of Conditions, |
* and the following Disclaimer and Export Compliance provision. In addition, |
* Licensee must cause all Covered Code to which Licensee contributes to |
* contain a file documenting the changes Licensee made to create that Covered |
* Code and the date of any change. Licensee must include in that file the |
* documentation of any changes made by any predecessor Licensee. Licensee |
* must include a prominent statement that the modification is derived, |
* directly or indirectly, from Original Intel Code. |
* |
* 3.2. Redistribution of Source with no Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification without rights to further distribute source must |
* include the following Disclaimer and Export Compliance provision in the |
* documentation and/or other materials provided with distribution. In |
* addition, Licensee may not authorize further sublicense of source of any |
* portion of the Covered Code, and must include terms to the effect that the |
* license from Licensee to its licensee is limited to the intellectual |
* property embodied in the software Licensee provides to its licensee, and |
* not to intellectual property embodied in modifications its licensee may |
* make. |
* |
* 3.3. Redistribution of Executable. Redistribution in executable form of any |
* substantial portion of the Covered Code or modification must reproduce the |
* above Copyright Notice, and the following Disclaimer and Export Compliance |
* provision in the documentation and/or other materials provided with the |
* distribution. |
* |
* 3.4. Intel retains all right, title, and interest in and to the Original |
* Intel Code. |
* |
* 3.5. Neither the name Intel nor any other trademark owned or controlled by |
* Intel shall be used in advertising or otherwise to promote the sale, use or |
* other dealings in products derived from or relating to the Covered Code |
* without prior written authorization from Intel. |
* |
* 4. Disclaimer and Export Compliance |
* |
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED |
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE |
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, |
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY |
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY |
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A |
* PARTICULAR PURPOSE. |
* |
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES |
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR |
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, |
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY |
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL |
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS |
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY |
* LIMITED REMEDY. |
* |
* 4.3. Licensee shall not export, either directly or indirectly, any of this |
* software or system incorporating such software without first obtaining any |
* required license or other approval from the U. S. Department of Commerce or |
* any other agency or department of the United States Government. In the |
* event Licensee exports any such software from the United States or |
* re-exports any such software from a foreign destination, Licensee shall |
* ensure that the distribution and export/re-export of the software is in |
* compliance with all laws, regulations, orders, or other restrictions of the |
* U.S. Export Administration Regulations. Licensee agrees that neither it nor |
* any of its subsidiaries will export/re-export any technical data, process, |
* software, or service, directly or indirectly, to any country for which the |
* United States government or any agency thereof requires an export license, |
* other governmental approval, or letter of assurance, without first obtaining |
* such license, approval or letter. |
* |
*****************************************************************************/ |
#include "acpi.h" |
#include "accommon.h" |
#include "acevents.h" |
#include "acinterp.h" |
#define _COMPONENT ACPI_EVENTS |
ACPI_MODULE_NAME ("evglock") |
/* Local prototypes */ |
static UINT32 |
AcpiEvGlobalLockHandler ( |
void *Context); |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvInitGlobalLockHandler |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Install a handler for the global lock release event |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvInitGlobalLockHandler ( |
void) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvInitGlobalLockHandler); |
/* Attempt installation of the global lock handler */ |
Status = AcpiInstallFixedEventHandler (ACPI_EVENT_GLOBAL, |
AcpiEvGlobalLockHandler, NULL); |
/* |
* If the global lock does not exist on this platform, the attempt to |
* enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick). |
* Map to AE_OK, but mark global lock as not present. Any attempt to |
* actually use the global lock will be flagged with an error. |
*/ |
AcpiGbl_GlobalLockPresent = FALSE; |
if (Status == AE_NO_HARDWARE_RESPONSE) |
{ |
ACPI_ERROR ((AE_INFO, |
"No response from Global Lock hardware, disabling lock")); |
return_ACPI_STATUS (AE_OK); |
} |
Status = AcpiOsCreateLock (&AcpiGbl_GlobalLockPendingLock); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
AcpiGbl_GlobalLockPending = FALSE; |
AcpiGbl_GlobalLockPresent = TRUE; |
return_ACPI_STATUS (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvRemoveGlobalLockHandler |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Remove the handler for the Global Lock |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvRemoveGlobalLockHandler ( |
void) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvRemoveGlobalLockHandler); |
AcpiGbl_GlobalLockPresent = FALSE; |
Status = AcpiRemoveFixedEventHandler (ACPI_EVENT_GLOBAL, |
AcpiEvGlobalLockHandler); |
return_ACPI_STATUS (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvGlobalLockHandler |
* |
* PARAMETERS: Context - From thread interface, not used |
* |
* RETURN: ACPI_INTERRUPT_HANDLED |
* |
* DESCRIPTION: Invoked directly from the SCI handler when a global lock |
* release interrupt occurs. If there is actually a pending |
* request for the lock, signal the waiting thread. |
* |
******************************************************************************/ |
static UINT32 |
AcpiEvGlobalLockHandler ( |
void *Context) |
{ |
ACPI_STATUS Status; |
ACPI_CPU_FLAGS Flags; |
Flags = AcpiOsAcquireLock (AcpiGbl_GlobalLockPendingLock); |
/* |
* If a request for the global lock is not actually pending, |
* we are done. This handles "spurious" global lock interrupts |
* which are possible (and have been seen) with bad BIOSs. |
*/ |
if (!AcpiGbl_GlobalLockPending) |
{ |
goto CleanupAndExit; |
} |
/* |
* Send a unit to the global lock semaphore. The actual acquisition |
* of the global lock will be performed by the waiting thread. |
*/ |
Status = AcpiOsSignalSemaphore (AcpiGbl_GlobalLockSemaphore, 1); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_ERROR ((AE_INFO, "Could not signal Global Lock semaphore")); |
} |
AcpiGbl_GlobalLockPending = FALSE; |
CleanupAndExit: |
AcpiOsReleaseLock (AcpiGbl_GlobalLockPendingLock, Flags); |
return (ACPI_INTERRUPT_HANDLED); |
} |
/****************************************************************************** |
* |
* FUNCTION: AcpiEvAcquireGlobalLock |
* |
* PARAMETERS: Timeout - Max time to wait for the lock, in millisec. |
* |
* RETURN: Status |
* |
* DESCRIPTION: Attempt to gain ownership of the Global Lock. |
* |
* MUTEX: Interpreter must be locked |
* |
* Note: The original implementation allowed multiple threads to "acquire" the |
* Global Lock, and the OS would hold the lock until the last thread had |
* released it. However, this could potentially starve the BIOS out of the |
* lock, especially in the case where there is a tight handshake between the |
* Embedded Controller driver and the BIOS. Therefore, this implementation |
* allows only one thread to acquire the HW Global Lock at a time, and makes |
* the global lock appear as a standard mutex on the OS side. |
* |
*****************************************************************************/ |
ACPI_STATUS |
AcpiEvAcquireGlobalLock ( |
UINT16 Timeout) |
{ |
ACPI_CPU_FLAGS Flags; |
ACPI_STATUS Status; |
BOOLEAN Acquired = FALSE; |
ACPI_FUNCTION_TRACE (EvAcquireGlobalLock); |
/* |
* Only one thread can acquire the GL at a time, the GlobalLockMutex |
* enforces this. This interface releases the interpreter if we must wait. |
*/ |
Status = AcpiExSystemWaitMutex (AcpiGbl_GlobalLockMutex->Mutex.OsMutex, |
Timeout); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* |
* Update the global lock handle and check for wraparound. The handle is |
* only used for the external global lock interfaces, but it is updated |
* here to properly handle the case where a single thread may acquire the |
* lock via both the AML and the AcpiAcquireGlobalLock interfaces. The |
* handle is therefore updated on the first acquire from a given thread |
* regardless of where the acquisition request originated. |
*/ |
AcpiGbl_GlobalLockHandle++; |
if (AcpiGbl_GlobalLockHandle == 0) |
{ |
AcpiGbl_GlobalLockHandle = 1; |
} |
/* |
* Make sure that a global lock actually exists. If not, just |
* treat the lock as a standard mutex. |
*/ |
if (!AcpiGbl_GlobalLockPresent) |
{ |
AcpiGbl_GlobalLockAcquired = TRUE; |
return_ACPI_STATUS (AE_OK); |
} |
Flags = AcpiOsAcquireLock (AcpiGbl_GlobalLockPendingLock); |
do |
{ |
/* Attempt to acquire the actual hardware lock */ |
ACPI_ACQUIRE_GLOBAL_LOCK (AcpiGbl_FACS, Acquired); |
if (Acquired) |
{ |
AcpiGbl_GlobalLockAcquired = TRUE; |
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, |
"Acquired hardware Global Lock\n")); |
break; |
} |
/* |
* Did not get the lock. The pending bit was set above, and |
* we must now wait until we receive the global lock |
* released interrupt. |
*/ |
AcpiGbl_GlobalLockPending = TRUE; |
AcpiOsReleaseLock (AcpiGbl_GlobalLockPendingLock, Flags); |
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, |
"Waiting for hardware Global Lock\n")); |
/* |
* Wait for handshake with the global lock interrupt handler. |
* This interface releases the interpreter if we must wait. |
*/ |
Status = AcpiExSystemWaitSemaphore (AcpiGbl_GlobalLockSemaphore, |
ACPI_WAIT_FOREVER); |
Flags = AcpiOsAcquireLock (AcpiGbl_GlobalLockPendingLock); |
} while (ACPI_SUCCESS (Status)); |
AcpiGbl_GlobalLockPending = FALSE; |
AcpiOsReleaseLock (AcpiGbl_GlobalLockPendingLock, Flags); |
return_ACPI_STATUS (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvReleaseGlobalLock |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Releases ownership of the Global Lock. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvReleaseGlobalLock ( |
void) |
{ |
BOOLEAN Pending = FALSE; |
ACPI_STATUS Status = AE_OK; |
ACPI_FUNCTION_TRACE (EvReleaseGlobalLock); |
/* Lock must be already acquired */ |
if (!AcpiGbl_GlobalLockAcquired) |
{ |
ACPI_WARNING ((AE_INFO, |
"Cannot release the ACPI Global Lock, it has not been acquired")); |
return_ACPI_STATUS (AE_NOT_ACQUIRED); |
} |
if (AcpiGbl_GlobalLockPresent) |
{ |
/* Allow any thread to release the lock */ |
ACPI_RELEASE_GLOBAL_LOCK (AcpiGbl_FACS, Pending); |
/* |
* If the pending bit was set, we must write GBL_RLS to the control |
* register |
*/ |
if (Pending) |
{ |
Status = AcpiWriteBitRegister ( |
ACPI_BITREG_GLOBAL_LOCK_RELEASE, ACPI_ENABLE_EVENT); |
} |
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Released hardware Global Lock\n")); |
} |
AcpiGbl_GlobalLockAcquired = FALSE; |
/* Release the local GL mutex */ |
AcpiOsReleaseMutex (AcpiGbl_GlobalLockMutex->Mutex.OsMutex); |
return_ACPI_STATUS (Status); |
} |
/drivers/devman/acpica/events/evgpe.c |
---|
8,7 → 8,7 |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
134,26 → 134,26 |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvUpdateGpeEnableMasks |
* FUNCTION: AcpiEvUpdateGpeEnableMask |
* |
* PARAMETERS: GpeEventInfo - GPE to update |
* |
* RETURN: Status |
* |
* DESCRIPTION: Updates GPE register enable masks based upon whether there are |
* references (either wake or run) to this GPE |
* DESCRIPTION: Updates GPE register enable mask based upon whether there are |
* runtime references to this GPE |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvUpdateGpeEnableMasks ( |
AcpiEvUpdateGpeEnableMask ( |
ACPI_GPE_EVENT_INFO *GpeEventInfo) |
{ |
ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; |
UINT8 RegisterBit; |
UINT32 RegisterBit; |
ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMasks); |
ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMask); |
GpeRegisterInfo = GpeEventInfo->RegisterInfo; |
162,26 → 162,19 |
return_ACPI_STATUS (AE_NOT_EXIST); |
} |
RegisterBit = (UINT8) |
(1 << (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber)); |
RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo); |
/* Clear the wake/run bits up front */ |
/* Clear the run bit up front */ |
ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit); |
ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit); |
/* Set the mask bits only if there are references to this GPE */ |
/* Set the mask bit only if there are references to this GPE */ |
if (GpeEventInfo->RuntimeCount) |
{ |
ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, RegisterBit); |
ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, (UINT8) RegisterBit); |
} |
if (GpeEventInfo->WakeupCount) |
{ |
ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, RegisterBit); |
} |
return_ACPI_STATUS (AE_OK); |
} |
194,11 → 187,8 |
* |
* RETURN: Status |
* |
* DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless |
* of type or number of references. |
* DESCRIPTION: Clear a GPE of stale events and enable it. |
* |
* Note: The GPE lock should be already acquired when this function is called. |
* |
******************************************************************************/ |
ACPI_STATUS |
212,24 → 202,17 |
/* |
* We will only allow a GPE to be enabled if it has either an |
* associated method (_Lxx/_Exx) or a handler. Otherwise, the |
* GPE will be immediately disabled by AcpiEvGpeDispatch the |
* first time it fires. |
* We will only allow a GPE to be enabled if it has either an associated |
* method (_Lxx/_Exx) or a handler, or is using the implicit notify |
* feature. Otherwise, the GPE will be immediately disabled by |
* AcpiEvGpeDispatch the first time it fires. |
*/ |
if (!(GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)) |
if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == |
ACPI_GPE_DISPATCH_NONE) |
{ |
return_ACPI_STATUS (AE_NO_HANDLER); |
} |
/* Ensure the HW enable masks are current */ |
Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* Clear the GPE (of stale events) */ |
Status = AcpiHwClearGpe (GpeEventInfo); |
240,7 → 223,7 |
/* Enable the requested GPE */ |
Status = AcpiHwWriteGpeEnableReg (GpeEventInfo); |
Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE); |
return_ACPI_STATUS (Status); |
} |
247,52 → 230,98 |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvDisableGpe |
* FUNCTION: AcpiEvAddGpeReference |
* |
* PARAMETERS: GpeEventInfo - GPE to disable |
* PARAMETERS: GpeEventInfo - Add a reference to this GPE |
* |
* RETURN: Status |
* |
* DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE, |
* regardless of the type or number of references. |
* DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is |
* hardware-enabled. |
* |
* Note: The GPE lock should be already acquired when this function is called. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvDisableGpe ( |
AcpiEvAddGpeReference ( |
ACPI_GPE_EVENT_INFO *GpeEventInfo) |
{ |
ACPI_STATUS Status; |
ACPI_STATUS Status = AE_OK; |
ACPI_FUNCTION_TRACE (EvDisableGpe); |
ACPI_FUNCTION_TRACE (EvAddGpeReference); |
/* |
* Note: Always disable the GPE, even if we think that that it is already |
* disabled. It is possible that the AML or some other code has enabled |
* the GPE behind our back. |
*/ |
if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX) |
{ |
return_ACPI_STATUS (AE_LIMIT); |
} |
/* Ensure the HW enable masks are current */ |
GpeEventInfo->RuntimeCount++; |
if (GpeEventInfo->RuntimeCount == 1) |
{ |
/* Enable on first reference */ |
Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo); |
Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo); |
if (ACPI_SUCCESS (Status)) |
{ |
Status = AcpiEvEnableGpe (GpeEventInfo); |
} |
if (ACPI_FAILURE (Status)) |
{ |
GpeEventInfo->RuntimeCount--; |
} |
} |
return_ACPI_STATUS (Status); |
} |
/* |
* Always H/W disable this GPE, even if we don't know the GPE type. |
* Simply clear the enable bit for this particular GPE, but do not |
* write out the current GPE enable mask since this may inadvertently |
* enable GPEs too early. An example is a rogue GPE that has arrived |
* during ACPICA initialization - possibly because AML or other code |
* has enabled the GPE. |
*/ |
Status = AcpiHwLowDisableGpe (GpeEventInfo); |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvRemoveGpeReference |
* |
* PARAMETERS: GpeEventInfo - Remove a reference to this GPE |
* |
* RETURN: Status |
* |
* DESCRIPTION: Remove a reference to a GPE. When the last reference is |
* removed, the GPE is hardware-disabled. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvRemoveGpeReference ( |
ACPI_GPE_EVENT_INFO *GpeEventInfo) |
{ |
ACPI_STATUS Status = AE_OK; |
ACPI_FUNCTION_TRACE (EvRemoveGpeReference); |
if (!GpeEventInfo->RuntimeCount) |
{ |
return_ACPI_STATUS (AE_LIMIT); |
} |
GpeEventInfo->RuntimeCount--; |
if (!GpeEventInfo->RuntimeCount) |
{ |
/* Disable on last reference */ |
Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo); |
if (ACPI_SUCCESS (Status)) |
{ |
Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); |
} |
if (ACPI_FAILURE (Status)) |
{ |
GpeEventInfo->RuntimeCount++; |
} |
} |
return_ACPI_STATUS (Status); |
} |
465,6 → 494,16 |
GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; |
/* |
* Optimization: If there are no GPEs enabled within this |
* register, we can safely ignore the entire register. |
*/ |
if (!(GpeRegisterInfo->EnableForRun | |
GpeRegisterInfo->EnableForWake)) |
{ |
continue; |
} |
/* Read the Status Register */ |
Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress); |
482,7 → 521,7 |
} |
ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, |
"Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n", |
"Read GPE Register at GPE%02X: Status=%02X, Enable=%02X\n", |
GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg)); |
/* Check if there is anything active at all in this register */ |
507,7 → 546,7 |
* Found an active GPE. Dispatch the event to a handler |
* or method. |
*/ |
IntStatus |= AcpiEvGpeDispatch ( |
IntStatus |= AcpiEvGpeDispatch (GpeBlock->Node, |
&GpeBlock->EventInfo[((ACPI_SIZE) i * |
ACPI_GPE_REGISTER_WIDTH) + j], |
j + GpeRegisterInfo->BaseGpeNumber); |
578,10 → 617,6 |
return_VOID; |
} |
/* Update the GPE register masks for return to enabled state */ |
(void) AcpiEvUpdateGpeEnableMasks (GpeEventInfo); |
/* |
* Take a snapshot of the GPE info for this level - we copy the info to |
* prevent a race condition with RemoveHandler/RemoveBlock. |
595,13 → 630,27 |
return_VOID; |
} |
/* Do the correct dispatch - normal method or implicit notify */ |
switch (LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) |
{ |
case ACPI_GPE_DISPATCH_NOTIFY: |
/* |
* Must check for control method type dispatch one more time to avoid a |
* race with EvGpeInstallHandler |
* Implicit notify. |
* Dispatch a DEVICE_WAKE notify to the appropriate handler. |
* NOTE: the request is queued for execution after this method |
* completes. The notify handlers are NOT invoked synchronously |
* from this thread -- because handlers may in turn run other |
* control methods. |
*/ |
if ((LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == |
ACPI_GPE_DISPATCH_METHOD) |
{ |
Status = AcpiEvQueueNotifyRequest ( |
LocalGpeEventInfo->Dispatch.DeviceNode, |
ACPI_NOTIFY_DEVICE_WAKE); |
break; |
case ACPI_GPE_DISPATCH_METHOD: |
/* Allocate the evaluation information block */ |
Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); |
612,8 → 661,8 |
else |
{ |
/* |
* Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx |
* control method that corresponds to this GPE |
* Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the |
* _Lxx/_Exx control method that corresponds to this GPE |
*/ |
Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode; |
Info->Flags = ACPI_IGNORE_RETURN_VALUE; |
628,6 → 677,11 |
"while evaluating GPE method [%4.4s]", |
AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode))); |
} |
break; |
default: |
return_VOID; /* Should never happen */ |
} |
/* Defer enabling of GPE until all notify handlers are done */ |
647,6 → 701,7 |
* FUNCTION: AcpiEvAsynchEnableGpe |
* |
* PARAMETERS: Context (GpeEventInfo) - Info for this GPE |
* Callback from AcpiOsExecute |
* |
* RETURN: None |
* |
660,6 → 715,32 |
void *Context) |
{ |
ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; |
(void) AcpiEvFinishGpe (GpeEventInfo); |
ACPI_FREE (GpeEventInfo); |
return; |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvFinishGpe |
* |
* PARAMETERS: GpeEventInfo - Info for this GPE |
* |
* RETURN: Status |
* |
* DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution |
* of a GPE method or a synchronous or asynchronous GPE handler. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvFinishGpe ( |
ACPI_GPE_EVENT_INFO *GpeEventInfo) |
{ |
ACPI_STATUS Status; |
667,23 → 748,23 |
ACPI_GPE_LEVEL_TRIGGERED) |
{ |
/* |
* GPE is level-triggered, we clear the GPE status bit after handling |
* the event. |
* GPE is level-triggered, we clear the GPE status bit after |
* handling the event. |
*/ |
Status = AcpiHwClearGpe (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
goto Exit; |
return (Status); |
} |
} |
/* Enable this GPE */ |
(void) AcpiHwWriteGpeEnableReg (GpeEventInfo); |
Exit: |
ACPI_FREE (GpeEventInfo); |
return; |
/* |
* Enable this GPE, conditionally. This means that the GPE will |
* only be physically enabled if the EnableForRun bit is set |
* in the EventInfo. |
*/ |
(void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE); |
return (AE_OK); |
} |
691,7 → 772,8 |
* |
* FUNCTION: AcpiEvGpeDispatch |
* |
* PARAMETERS: GpeEventInfo - Info for this GPE |
* PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1 |
* GpeEventInfo - Info for this GPE |
* GpeNumber - Number relative to the parent GPE block |
* |
* RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED |
705,16 → 787,25 |
UINT32 |
AcpiEvGpeDispatch ( |
ACPI_NAMESPACE_NODE *GpeDevice, |
ACPI_GPE_EVENT_INFO *GpeEventInfo, |
UINT32 GpeNumber) |
{ |
ACPI_STATUS Status; |
UINT32 ReturnValue; |
ACPI_FUNCTION_TRACE (EvGpeDispatch); |
/* Invoke global event handler if present */ |
AcpiGpeCount++; |
if (AcpiGbl_GlobalEventHandler) |
{ |
AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_GPE, GpeDevice, |
GpeNumber, AcpiGbl_GlobalEventHandlerContext); |
} |
/* |
* If edge-triggered, clear the GPE status bit now. Note that |
727,60 → 818,57 |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Unable to clear GPE[0x%2X]", GpeNumber)); |
"Unable to clear GPE%02X", GpeNumber)); |
return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); |
} |
} |
/* |
* Dispatch the GPE to either an installed handler, or the control method |
* associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke |
* it and do not attempt to run the method. If there is neither a handler |
* nor a method, we disable this GPE to prevent further such pointless |
* events from firing. |
* Always disable the GPE so that it does not keep firing before |
* any asynchronous activity completes (either from the execution |
* of a GPE method or an asynchronous GPE handler.) |
* |
* If there is no handler or method to run, just disable the |
* GPE and leave it disabled permanently to prevent further such |
* pointless events from firing. |
*/ |
Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Unable to disable GPE%02X", GpeNumber)); |
return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); |
} |
/* |
* Dispatch the GPE to either an installed handler or the control |
* method associated with this GPE (_Lxx or _Exx). If a handler |
* exists, we invoke it and do not attempt to run the method. |
* If there is neither a handler nor a method, leave the GPE |
* disabled. |
*/ |
switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) |
{ |
case ACPI_GPE_DISPATCH_HANDLER: |
/* |
* Invoke the installed handler (at interrupt level) |
* Ignore return status for now. |
* TBD: leave GPE disabled on error? |
*/ |
(void) GpeEventInfo->Dispatch.Handler->Address ( |
/* Invoke the installed handler (at interrupt level) */ |
ReturnValue = GpeEventInfo->Dispatch.Handler->Address ( |
GpeDevice, GpeNumber, |
GpeEventInfo->Dispatch.Handler->Context); |
/* It is now safe to clear level-triggered events. */ |
/* If requested, clear (if level-triggered) and reenable the GPE */ |
if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == |
ACPI_GPE_LEVEL_TRIGGERED) |
if (ReturnValue & ACPI_REENABLE_GPE) |
{ |
Status = AcpiHwClearGpe (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Unable to clear GPE[0x%2X]", GpeNumber)); |
return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); |
(void) AcpiEvFinishGpe (GpeEventInfo); |
} |
} |
break; |
case ACPI_GPE_DISPATCH_METHOD: |
case ACPI_GPE_DISPATCH_NOTIFY: |
/* |
* Disable the GPE, so it doesn't keep firing before the method has a |
* chance to run (it runs asynchronously with interrupts enabled). |
*/ |
Status = AcpiEvDisableGpe (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Unable to disable GPE[0x%2X]", GpeNumber)); |
return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); |
} |
/* |
* Execute the method associated with the GPE |
* NOTE: Level-triggered GPEs are cleared after the method completes. |
*/ |
789,7 → 877,7 |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Unable to queue handler for GPE[0x%2X] - event disabled", |
"Unable to queue handler for GPE%02X - event disabled", |
GpeNumber)); |
} |
break; |
802,20 → 890,8 |
* a GPE to be enabled if it has no handler or method. |
*/ |
ACPI_ERROR ((AE_INFO, |
"No handler or method for GPE[0x%2X], disabling event", |
"No handler or method for GPE%02X, disabling event", |
GpeNumber)); |
/* |
* Disable the GPE. The GPE will remain disabled a handler |
* is installed or ACPICA is restarted. |
*/ |
Status = AcpiEvDisableGpe (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Unable to disable GPE[0x%2X]", GpeNumber)); |
return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); |
} |
break; |
} |
/drivers/devman/acpica/events/evgpeblk.c |
---|
8,7 → 8,7 |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
467,6 → 467,7 |
GpeBlock->Node = GpeDevice; |
GpeBlock->GpeCount = (UINT16) (RegisterCount * ACPI_GPE_REGISTER_WIDTH); |
GpeBlock->Initialized = FALSE; |
GpeBlock->RegisterCount = RegisterCount; |
GpeBlock->BlockBaseNumber = GpeBlockBaseNumber; |
493,11 → 494,12 |
return_ACPI_STATUS (Status); |
} |
AcpiGbl_AllGpesInitialized = FALSE; |
/* Find all GPE methods (_Lxx or_Exx) for this block */ |
WalkInfo.GpeBlock = GpeBlock; |
WalkInfo.GpeDevice = GpeDevice; |
WalkInfo.EnableThisGpe = FALSE; |
WalkInfo.ExecuteByOwnerId = FALSE; |
Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, GpeDevice, |
529,14 → 531,12 |
* |
* FUNCTION: AcpiEvInitializeGpeBlock |
* |
* PARAMETERS: GpeDevice - Handle to the parent GPE block |
* GpeBlock - Gpe Block info |
* PARAMETERS: ACPI_GPE_CALLBACK |
* |
* RETURN: Status |
* |
* DESCRIPTION: Initialize and enable a GPE block. First find and run any |
* _PRT methods associated with the block, then enable the |
* appropriate GPEs. |
* DESCRIPTION: Initialize and enable a GPE block. Enable GPEs that have |
* associated methods. |
* Note: Assumes namespace is locked. |
* |
******************************************************************************/ |
543,16 → 543,14 |
ACPI_STATUS |
AcpiEvInitializeGpeBlock ( |
ACPI_NAMESPACE_NODE *GpeDevice, |
ACPI_GPE_BLOCK_INFO *GpeBlock) |
ACPI_GPE_XRUPT_INFO *GpeXruptInfo, |
ACPI_GPE_BLOCK_INFO *GpeBlock, |
void *Ignored) |
{ |
ACPI_STATUS Status; |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_GPE_WALK_INFO WalkInfo; |
UINT32 WakeGpeCount; |
UINT32 GpeEnabledCount; |
UINT32 GpeIndex; |
UINT32 GpeNumber; |
UINT32 i; |
UINT32 j; |
560,51 → 558,22 |
ACPI_FUNCTION_TRACE (EvInitializeGpeBlock); |
/* Ignore a null GPE block (e.g., if no GPE block 1 exists) */ |
if (!GpeBlock) |
{ |
return_ACPI_STATUS (AE_OK); |
} |
/* |
* Runtime option: Should wake GPEs be enabled at runtime? The default |
* is no, they should only be enabled just as the machine goes to sleep. |
* Ignore a null GPE block (e.g., if no GPE block 1 exists), and |
* any GPE blocks that have been initialized already. |
*/ |
if (AcpiGbl_LeaveWakeGpesDisabled) |
if (!GpeBlock || GpeBlock->Initialized) |
{ |
/* |
* Differentiate runtime vs wake GPEs, via the _PRW control methods. |
* Each GPE that has one or more _PRWs that reference it is by |
* definition a wake GPE and will not be enabled while the machine |
* is running. |
*/ |
WalkInfo.GpeBlock = GpeBlock; |
WalkInfo.GpeDevice = GpeDevice; |
WalkInfo.ExecuteByOwnerId = FALSE; |
Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, |
ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, |
AcpiEvMatchPrwAndGpe, NULL, &WalkInfo, NULL); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, "While executing _PRW methods")); |
return_ACPI_STATUS (AE_OK); |
} |
} |
/* |
* Enable all GPEs that have a corresponding method and are not |
* capable of generating wakeups. Any other GPEs within this block |
* must be enabled via the AcpiEnableGpe interface. |
* Enable all GPEs that have a corresponding method and have the |
* ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block |
* must be enabled via the acpi_enable_gpe() interface. |
*/ |
WakeGpeCount = 0; |
GpeEnabledCount = 0; |
if (GpeDevice == AcpiGbl_FadtGpeDevice) |
{ |
GpeDevice = NULL; |
} |
for (i = 0; i < GpeBlock->RegisterCount; i++) |
{ |
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) |
614,33 → 583,23 |
GpeIndex = (i * ACPI_GPE_REGISTER_WIDTH) + j; |
GpeEventInfo = &GpeBlock->EventInfo[GpeIndex]; |
/* Ignore GPEs that can wake the system */ |
if (GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE) |
/* |
* Ignore GPEs that have no corresponding _Lxx/_Exx method |
* and GPEs that are used to wake the system |
*/ |
if (((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_NONE) || |
((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) || |
(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) |
{ |
WakeGpeCount++; |
if (AcpiGbl_LeaveWakeGpesDisabled) |
{ |
continue; |
} |
} |
/* Ignore GPEs that have no corresponding _Lxx/_Exx method */ |
if (!(GpeEventInfo->Flags & ACPI_GPE_DISPATCH_METHOD)) |
{ |
continue; |
} |
/* Enable this GPE */ |
GpeNumber = GpeIndex + GpeBlock->BlockBaseNumber; |
Status = AcpiEnableGpe (GpeDevice, GpeNumber, |
ACPI_GPE_TYPE_RUNTIME); |
Status = AcpiEvAddGpeReference (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Could not enable GPE 0x%02X", GpeNumber)); |
"Could not enable GPE 0x%02X", |
GpeIndex + GpeBlock->BlockBaseNumber)); |
continue; |
} |
648,13 → 607,13 |
} |
} |
if (GpeEnabledCount || WakeGpeCount) |
if (GpeEnabledCount) |
{ |
ACPI_DEBUG_PRINT ((ACPI_DB_INIT, |
"Enabled %u Runtime GPEs, added %u Wake GPEs in this block\n", |
GpeEnabledCount, WakeGpeCount)); |
"Enabled %u GPEs in this block\n", GpeEnabledCount)); |
} |
GpeBlock->Initialized = TRUE; |
return_ACPI_STATUS (AE_OK); |
} |
/drivers/devman/acpica/events/evgpeinit.c |
---|
8,7 → 8,7 |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
118,12 → 118,28 |
#include "accommon.h" |
#include "acevents.h" |
#include "acnamesp.h" |
#include "acinterp.h" |
#define _COMPONENT ACPI_EVENTS |
ACPI_MODULE_NAME ("evgpeinit") |
/* |
* Note: History of _PRW support in ACPICA |
* |
* Originally (2000 - 2010), the GPE initialization code performed a walk of |
* the entire namespace to execute the _PRW methods and detect all GPEs |
* capable of waking the system. |
* |
* As of 10/2010, the _PRW method execution has been removed since it is |
* actually unnecessary. The host OS must in fact execute all _PRW methods |
* in order to identify the device/power-resource dependencies. We now put |
* the onus on the host OS to identify the wake GPEs as part of this process |
* and to inform ACPICA of these GPEs via the AcpiSetupGpeForWake interface. This |
* not only reduces the complexity of the ACPICA initialization code, but in |
* some cases (on systems with very large namespaces) it should reduce the |
* kernel boot time as well. |
*/ |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvGpeInitialize |
288,10 → 304,7 |
* |
* DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a |
* result of a Load() or LoadTable() operation. If new GPE |
* methods have been installed, register the new methods and |
* enable and runtime GPEs that are associated with them. Also, |
* run any newly loaded _PRW methods in order to discover any |
* new CAN_WAKE GPEs. |
* methods have been installed, register the new methods. |
* |
******************************************************************************/ |
303,50 → 316,14 |
ACPI_GPE_BLOCK_INFO *GpeBlock; |
ACPI_GPE_WALK_INFO WalkInfo; |
ACPI_STATUS Status = AE_OK; |
UINT32 NewWakeGpeCount = 0; |
/* We will examine only _PRW/_Lxx/_Exx methods owned by this table */ |
WalkInfo.OwnerId = TableOwnerId; |
WalkInfo.ExecuteByOwnerId = TRUE; |
WalkInfo.Count = 0; |
if (AcpiGbl_LeaveWakeGpesDisabled) |
{ |
/* |
* 1) Run any newly-loaded _PRW methods to find any GPEs that |
* can now be marked as CAN_WAKE GPEs. Note: We must run the |
* _PRW methods before we process the _Lxx/_Exx methods because |
* we will enable all runtime GPEs associated with the new |
* _Lxx/_Exx methods at the time we process those methods. |
* Find any _Lxx/_Exx GPE methods that have just been loaded. |
* |
* Unlock interpreter so that we can run the _PRW methods. |
*/ |
WalkInfo.GpeBlock = NULL; |
WalkInfo.GpeDevice = NULL; |
AcpiExExitInterpreter (); |
Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, |
ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, |
AcpiEvMatchPrwAndGpe, NULL, &WalkInfo, NULL); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"While executing _PRW methods")); |
} |
AcpiExEnterInterpreter (); |
NewWakeGpeCount = WalkInfo.Count; |
} |
/* |
* 2) Find any _Lxx/_Exx GPE methods that have just been loaded. |
* Any GPEs that correspond to new _Lxx/_Exx methods are immediately |
* enabled. |
* |
* Any GPEs that correspond to new _Lxx/_Exx methods and are not |
* marked as CAN_WAKE are immediately enabled. |
* |
* Examine the namespace underneath each GpeDevice within the |
* GpeBlock lists. |
*/ |
357,7 → 334,8 |
} |
WalkInfo.Count = 0; |
WalkInfo.EnableThisGpe = TRUE; |
WalkInfo.OwnerId = TableOwnerId; |
WalkInfo.ExecuteByOwnerId = TRUE; |
/* Walk the interrupt level descriptor list */ |
388,11 → 366,9 |
GpeXruptInfo = GpeXruptInfo->Next; |
} |
if (WalkInfo.Count || NewWakeGpeCount) |
if (WalkInfo.Count) |
{ |
ACPI_INFO ((AE_INFO, |
"Enabled %u new runtime GPEs, added %u new wakeup GPEs", |
WalkInfo.Count, NewWakeGpeCount)); |
ACPI_INFO ((AE_INFO, "Enabled %u new GPEs", WalkInfo.Count)); |
} |
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
423,8 → 399,6 |
* |
* If WalkInfo->ExecuteByOwnerId is TRUE, we only execute examine GPE methods |
* with that owner. |
* If WalkInfo->EnableThisGpe is TRUE, the GPE that is referred to by a GPE |
* method is immediately enabled (Used for Load/LoadTable operators) |
* |
******************************************************************************/ |
438,8 → 412,6 |
ACPI_NAMESPACE_NODE *MethodNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); |
ACPI_GPE_WALK_INFO *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context); |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_NAMESPACE_NODE *GpeDevice; |
ACPI_STATUS Status; |
UINT32 GpeNumber; |
char Name[ACPI_NAME_SIZE + 1]; |
UINT8 Type; |
474,9 → 446,6 |
/* |
* 3) Edge/Level determination is based on the 2nd character |
* of the method name |
* |
* NOTE: Default GPE type is RUNTIME only. Later, if a _PRW object is |
* found that points to this GPE, the ACPI_GPE_CAN_WAKE flag is set. |
*/ |
switch (Name[1]) |
{ |
551,213 → 520,12 |
* Add the GPE information from above to the GpeEventInfo block for |
* use during dispatch of this GPE. |
*/ |
GpeEventInfo->Flags &= ~(ACPI_GPE_DISPATCH_MASK); |
GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_METHOD); |
GpeEventInfo->Dispatch.MethodNode = MethodNode; |
/* |
* Enable this GPE if requested. This only happens when during the |
* execution of a Load or LoadTable operator. We have found a new |
* GPE method and want to immediately enable the GPE if it is a |
* runtime GPE. |
*/ |
if (WalkInfo->EnableThisGpe) |
{ |
/* Ignore GPEs that can wake the system */ |
if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE) || |
!AcpiGbl_LeaveWakeGpesDisabled) |
{ |
WalkInfo->Count++; |
GpeDevice = WalkInfo->GpeDevice; |
if (GpeDevice == AcpiGbl_FadtGpeDevice) |
{ |
GpeDevice = NULL; |
} |
Status = AcpiEnableGpe (GpeDevice, GpeNumber, |
ACPI_GPE_TYPE_RUNTIME); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Could not enable GPE 0x%02X", GpeNumber)); |
} |
} |
} |
ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, |
"Registered GPE method %s as GPE number 0x%.2X\n", |
Name, GpeNumber)); |
return_ACPI_STATUS (AE_OK); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvMatchPrwAndGpe |
* |
* PARAMETERS: Callback from WalkNamespace |
* |
* RETURN: Status. NOTE: We ignore errors so that the _PRW walk is |
* not aborted on a single _PRW failure. |
* |
* DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a |
* Device. Run the _PRW method. If present, extract the GPE |
* number and mark the GPE as a CAN_WAKE GPE. Allows a |
* per-OwnerId execution if ExecuteByOwnerId is TRUE in the |
* WalkInfo parameter block. |
* |
* If WalkInfo->ExecuteByOwnerId is TRUE, we only execute _PRWs with that |
* owner. |
* If WalkInfo->GpeDevice is NULL, we execute every _PRW found. Otherwise, |
* we only execute _PRWs that refer to the input GpeDevice. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvMatchPrwAndGpe ( |
ACPI_HANDLE ObjHandle, |
UINT32 Level, |
void *Context, |
void **ReturnValue) |
{ |
ACPI_GPE_WALK_INFO *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context); |
ACPI_NAMESPACE_NODE *GpeDevice; |
ACPI_GPE_BLOCK_INFO *GpeBlock; |
ACPI_NAMESPACE_NODE *TargetGpeDevice; |
ACPI_NAMESPACE_NODE *PrwNode; |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_OPERAND_OBJECT *PkgDesc; |
ACPI_OPERAND_OBJECT *ObjDesc; |
UINT32 GpeNumber; |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvMatchPrwAndGpe); |
/* Check for a _PRW method under this device */ |
Status = AcpiNsGetNode (ObjHandle, METHOD_NAME__PRW, |
ACPI_NS_NO_UPSEARCH, &PrwNode); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (AE_OK); |
} |
/* Check if requested OwnerId matches this OwnerId */ |
if ((WalkInfo->ExecuteByOwnerId) && |
(PrwNode->OwnerId != WalkInfo->OwnerId)) |
{ |
return_ACPI_STATUS (AE_OK); |
} |
/* Execute the _PRW */ |
Status = AcpiUtEvaluateObject (PrwNode, NULL, |
ACPI_BTYPE_PACKAGE, &PkgDesc); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (AE_OK); |
} |
/* The returned _PRW package must have at least two elements */ |
if (PkgDesc->Package.Count < 2) |
{ |
goto Cleanup; |
} |
/* Extract pointers from the input context */ |
GpeDevice = WalkInfo->GpeDevice; |
GpeBlock = WalkInfo->GpeBlock; |
/* |
* The _PRW object must return a package, we are only interested |
* in the first element |
*/ |
ObjDesc = PkgDesc->Package.Elements[0]; |
if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER) |
{ |
/* Use FADT-defined GPE device (from definition of _PRW) */ |
TargetGpeDevice = NULL; |
if (GpeDevice) |
{ |
TargetGpeDevice = AcpiGbl_FadtGpeDevice; |
} |
/* Integer is the GPE number in the FADT described GPE blocks */ |
GpeNumber = (UINT32) ObjDesc->Integer.Value; |
} |
else if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE) |
{ |
/* Package contains a GPE reference and GPE number within a GPE block */ |
if ((ObjDesc->Package.Count < 2) || |
((ObjDesc->Package.Elements[0])->Common.Type != |
ACPI_TYPE_LOCAL_REFERENCE) || |
((ObjDesc->Package.Elements[1])->Common.Type != |
ACPI_TYPE_INTEGER)) |
{ |
goto Cleanup; |
} |
/* Get GPE block reference and decode */ |
TargetGpeDevice = ObjDesc->Package.Elements[0]->Reference.Node; |
GpeNumber = (UINT32) ObjDesc->Package.Elements[1]->Integer.Value; |
} |
else |
{ |
/* Unknown type, just ignore it */ |
goto Cleanup; |
} |
/* Get the GpeEventInfo for this GPE */ |
if (GpeDevice) |
{ |
/* |
* Is this GPE within this block? |
* |
* TRUE if and only if these conditions are true: |
* 1) The GPE devices match. |
* 2) The GPE index(number) is within the range of the Gpe Block |
* associated with the GPE device. |
*/ |
if (GpeDevice != TargetGpeDevice) |
{ |
goto Cleanup; |
} |
GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, GpeBlock); |
} |
else |
{ |
/* GpeDevice is NULL, just match the TargetDevice and GpeNumber */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (TargetGpeDevice, GpeNumber); |
} |
if (GpeEventInfo) |
{ |
if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) |
{ |
/* This GPE can wake the system */ |
GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; |
WalkInfo->Count++; |
} |
} |
Cleanup: |
AcpiUtRemoveReference (PkgDesc); |
return_ACPI_STATUS (AE_OK); |
} |
/drivers/devman/acpica/events/evgpeutil.c |
---|
8,7 → 8,7 |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
241,6 → 241,51 |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvGetGpeDevice |
* |
* PARAMETERS: GPE_WALK_CALLBACK |
* |
* RETURN: Status |
* |
* DESCRIPTION: Matches the input GPE index (0-CurrentGpeCount) with a GPE |
* block device. NULL if the GPE is one of the FADT-defined GPEs. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvGetGpeDevice ( |
ACPI_GPE_XRUPT_INFO *GpeXruptInfo, |
ACPI_GPE_BLOCK_INFO *GpeBlock, |
void *Context) |
{ |
ACPI_GPE_DEVICE_INFO *Info = Context; |
/* Increment Index by the number of GPEs in this block */ |
Info->NextBlockBaseIndex += GpeBlock->GpeCount; |
if (Info->Index < Info->NextBlockBaseIndex) |
{ |
/* |
* The GPE index is within this block, get the node. Leave the node |
* NULL for the FADT-defined GPEs |
*/ |
if ((GpeBlock->Node)->Type == ACPI_TYPE_DEVICE) |
{ |
Info->GpeDevice = GpeBlock->Node; |
} |
Info->Status = AE_OK; |
return (AE_CTRL_END); |
} |
return (AE_OK); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvGetGpeXruptBlock |
* |
* PARAMETERS: InterruptNumber - Interrupt for a GPE block |
/drivers/devman/acpica/events/evmisc.c |
---|
8,7 → 8,7 |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
117,7 → 117,6 |
#include "accommon.h" |
#include "acevents.h" |
#include "acnamesp.h" |
#include "acinterp.h" |
#define _COMPONENT ACPI_EVENTS |
ACPI_MODULE_NAME ("evmisc") |
129,15 → 128,7 |
AcpiEvNotifyDispatch ( |
void *Context); |
static UINT32 |
AcpiEvGlobalLockHandler ( |
void *Context); |
static ACPI_STATUS |
AcpiEvRemoveGlobalLockHandler ( |
void); |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvIsNotifyObject |
372,294 → 363,8 |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvGlobalLockHandler |
* |
* PARAMETERS: Context - From thread interface, not used |
* |
* RETURN: ACPI_INTERRUPT_HANDLED |
* |
* DESCRIPTION: Invoked directly from the SCI handler when a global lock |
* release interrupt occurs. Attempt to acquire the global lock, |
* if successful, signal the thread waiting for the lock. |
* |
* NOTE: Assumes that the semaphore can be signaled from interrupt level. If |
* this is not possible for some reason, a separate thread will have to be |
* scheduled to do this. |
* |
******************************************************************************/ |
static UINT32 |
AcpiEvGlobalLockHandler ( |
void *Context) |
{ |
BOOLEAN Acquired = FALSE; |
ACPI_STATUS Status; |
/* |
* Attempt to get the lock. |
* |
* If we don't get it now, it will be marked pending and we will |
* take another interrupt when it becomes free. |
*/ |
ACPI_ACQUIRE_GLOBAL_LOCK (AcpiGbl_FACS, Acquired); |
if (Acquired) |
{ |
/* Got the lock, now wake the thread waiting for it */ |
AcpiGbl_GlobalLockAcquired = TRUE; |
/* Send a unit to the semaphore */ |
Status = AcpiOsSignalSemaphore (AcpiGbl_GlobalLockSemaphore, 1); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_ERROR ((AE_INFO, "Could not signal Global Lock semaphore")); |
} |
} |
return (ACPI_INTERRUPT_HANDLED); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvInitGlobalLockHandler |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Install a handler for the global lock release event |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvInitGlobalLockHandler ( |
void) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvInitGlobalLockHandler); |
/* Attempt installation of the global lock handler */ |
Status = AcpiInstallFixedEventHandler (ACPI_EVENT_GLOBAL, |
AcpiEvGlobalLockHandler, NULL); |
/* |
* If the global lock does not exist on this platform, the attempt to |
* enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick). |
* Map to AE_OK, but mark global lock as not present. Any attempt to |
* actually use the global lock will be flagged with an error. |
*/ |
if (Status == AE_NO_HARDWARE_RESPONSE) |
{ |
ACPI_ERROR ((AE_INFO, |
"No response from Global Lock hardware, disabling lock")); |
AcpiGbl_GlobalLockPresent = FALSE; |
return_ACPI_STATUS (AE_OK); |
} |
AcpiGbl_GlobalLockPresent = TRUE; |
return_ACPI_STATUS (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvRemoveGlobalLockHandler |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Remove the handler for the Global Lock |
* |
******************************************************************************/ |
static ACPI_STATUS |
AcpiEvRemoveGlobalLockHandler ( |
void) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvRemoveGlobalLockHandler); |
AcpiGbl_GlobalLockPresent = FALSE; |
Status = AcpiRemoveFixedEventHandler (ACPI_EVENT_GLOBAL, |
AcpiEvGlobalLockHandler); |
return_ACPI_STATUS (Status); |
} |
/****************************************************************************** |
* |
* FUNCTION: AcpiEvAcquireGlobalLock |
* |
* PARAMETERS: Timeout - Max time to wait for the lock, in millisec. |
* |
* RETURN: Status |
* |
* DESCRIPTION: Attempt to gain ownership of the Global Lock. |
* |
* MUTEX: Interpreter must be locked |
* |
* Note: The original implementation allowed multiple threads to "acquire" the |
* Global Lock, and the OS would hold the lock until the last thread had |
* released it. However, this could potentially starve the BIOS out of the |
* lock, especially in the case where there is a tight handshake between the |
* Embedded Controller driver and the BIOS. Therefore, this implementation |
* allows only one thread to acquire the HW Global Lock at a time, and makes |
* the global lock appear as a standard mutex on the OS side. |
* |
*****************************************************************************/ |
ACPI_STATUS |
AcpiEvAcquireGlobalLock ( |
UINT16 Timeout) |
{ |
ACPI_STATUS Status = AE_OK; |
BOOLEAN Acquired = FALSE; |
ACPI_FUNCTION_TRACE (EvAcquireGlobalLock); |
/* |
* Only one thread can acquire the GL at a time, the GlobalLockMutex |
* enforces this. This interface releases the interpreter if we must wait. |
*/ |
Status = AcpiExSystemWaitMutex (AcpiGbl_GlobalLockMutex->Mutex.OsMutex, |
Timeout); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* |
* Update the global lock handle and check for wraparound. The handle is |
* only used for the external global lock interfaces, but it is updated |
* here to properly handle the case where a single thread may acquire the |
* lock via both the AML and the AcpiAcquireGlobalLock interfaces. The |
* handle is therefore updated on the first acquire from a given thread |
* regardless of where the acquisition request originated. |
*/ |
AcpiGbl_GlobalLockHandle++; |
if (AcpiGbl_GlobalLockHandle == 0) |
{ |
AcpiGbl_GlobalLockHandle = 1; |
} |
/* |
* Make sure that a global lock actually exists. If not, just treat the |
* lock as a standard mutex. |
*/ |
if (!AcpiGbl_GlobalLockPresent) |
{ |
AcpiGbl_GlobalLockAcquired = TRUE; |
return_ACPI_STATUS (AE_OK); |
} |
/* Attempt to acquire the actual hardware lock */ |
ACPI_ACQUIRE_GLOBAL_LOCK (AcpiGbl_FACS, Acquired); |
if (Acquired) |
{ |
/* We got the lock */ |
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Acquired hardware Global Lock\n")); |
AcpiGbl_GlobalLockAcquired = TRUE; |
return_ACPI_STATUS (AE_OK); |
} |
/* |
* Did not get the lock. The pending bit was set above, and we must now |
* wait until we get the global lock released interrupt. |
*/ |
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Waiting for hardware Global Lock\n")); |
/* |
* Wait for handshake with the global lock interrupt handler. |
* This interface releases the interpreter if we must wait. |
*/ |
Status = AcpiExSystemWaitSemaphore (AcpiGbl_GlobalLockSemaphore, |
ACPI_WAIT_FOREVER); |
return_ACPI_STATUS (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvReleaseGlobalLock |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Releases ownership of the Global Lock. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvReleaseGlobalLock ( |
void) |
{ |
BOOLEAN Pending = FALSE; |
ACPI_STATUS Status = AE_OK; |
ACPI_FUNCTION_TRACE (EvReleaseGlobalLock); |
/* Lock must be already acquired */ |
if (!AcpiGbl_GlobalLockAcquired) |
{ |
ACPI_WARNING ((AE_INFO, |
"Cannot release the ACPI Global Lock, it has not been acquired")); |
return_ACPI_STATUS (AE_NOT_ACQUIRED); |
} |
if (AcpiGbl_GlobalLockPresent) |
{ |
/* Allow any thread to release the lock */ |
ACPI_RELEASE_GLOBAL_LOCK (AcpiGbl_FACS, Pending); |
/* |
* If the pending bit was set, we must write GBL_RLS to the control |
* register |
*/ |
if (Pending) |
{ |
Status = AcpiWriteBitRegister ( |
ACPI_BITREG_GLOBAL_LOCK_RELEASE, ACPI_ENABLE_EVENT); |
} |
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Released hardware Global Lock\n")); |
} |
AcpiGbl_GlobalLockAcquired = FALSE; |
/* Release the local GL mutex */ |
AcpiOsReleaseMutex (AcpiGbl_GlobalLockMutex->Mutex.OsMutex); |
return_ACPI_STATUS (Status); |
} |
/****************************************************************************** |
* |
* FUNCTION: AcpiEvTerminate |
* |
* PARAMETERS: none |
737,4 → 442,3 |
} |
return_VOID; |
} |
/drivers/devman/acpica/events/evregion.c |
---|
8,7 → 8,7 |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
133,6 → 133,10 |
ACPI_NAMESPACE_NODE *Node, |
ACPI_ADR_SPACE_TYPE SpaceId); |
static void |
AcpiEvOrphanEcRegMethod ( |
void); |
static ACPI_STATUS |
AcpiEvRegRun ( |
ACPI_HANDLE ObjHandle, |
334,6 → 338,8 |
} |
} |
AcpiGbl_RegMethodsExecuted = TRUE; |
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
return_ACPI_STATUS (Status); |
} |
681,7 → 687,7 |
/* Now stop region accesses by executing the _REG method */ |
Status = AcpiEvExecuteRegMethod (RegionObj, 0); |
Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_DISCONNECT); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]", |
1212,6 → 1218,13 |
ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL, |
&SpaceId, NULL); |
/* Special case for EC: handle "orphan" _REG methods with no region */ |
if (SpaceId == ACPI_ADR_SPACE_EC) |
{ |
AcpiEvOrphanEcRegMethod (); |
} |
return_ACPI_STATUS (Status); |
} |
1278,7 → 1291,122 |
return (AE_OK); |
} |
Status = AcpiEvExecuteRegMethod (ObjDesc, 1); |
Status = AcpiEvExecuteRegMethod (ObjDesc, ACPI_REG_CONNECT); |
return (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvOrphanEcRegMethod |
* |
* PARAMETERS: None |
* |
* RETURN: None |
* |
* DESCRIPTION: Execute an "orphan" _REG method that appears under the EC |
* device. This is a _REG method that has no corresponding region |
* within the EC device scope. The orphan _REG method appears to |
* have been enabled by the description of the ECDT in the ACPI |
* specification: "The availability of the region space can be |
* detected by providing a _REG method object underneath the |
* Embedded Controller device." |
* |
* To quickly access the EC device, we use the EC_ID that appears |
* within the ECDT. Otherwise, we would need to perform a time- |
* consuming namespace walk, executing _HID methods to find the |
* EC device. |
* |
******************************************************************************/ |
static void |
AcpiEvOrphanEcRegMethod ( |
void) |
{ |
ACPI_TABLE_ECDT *Table; |
ACPI_STATUS Status; |
ACPI_OBJECT_LIST Args; |
ACPI_OBJECT Objects[2]; |
ACPI_NAMESPACE_NODE *EcDeviceNode; |
ACPI_NAMESPACE_NODE *RegMethod; |
ACPI_NAMESPACE_NODE *NextNode; |
ACPI_FUNCTION_TRACE (EvOrphanEcRegMethod); |
/* Get the ECDT (if present in system) */ |
Status = AcpiGetTable (ACPI_SIG_ECDT, 0, |
ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &Table)); |
if (ACPI_FAILURE (Status)) |
{ |
return_VOID; |
} |
/* We need a valid EC_ID string */ |
if (!(*Table->Id)) |
{ |
return_VOID; |
} |
/* Namespace is currently locked, must release */ |
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
/* Get a handle to the EC device referenced in the ECDT */ |
Status = AcpiGetHandle (NULL, |
ACPI_CAST_PTR (char, Table->Id), |
ACPI_CAST_PTR (ACPI_HANDLE, &EcDeviceNode)); |
if (ACPI_FAILURE (Status)) |
{ |
goto Exit; |
} |
/* Get a handle to a _REG method immediately under the EC device */ |
Status = AcpiGetHandle (EcDeviceNode, |
METHOD_NAME__REG, ACPI_CAST_PTR (ACPI_HANDLE, &RegMethod)); |
if (ACPI_FAILURE (Status)) |
{ |
goto Exit; |
} |
/* |
* Execute the _REG method only if there is no Operation Region in |
* this scope with the Embedded Controller space ID. Otherwise, it |
* will already have been executed. Note, this allows for Regions |
* with other space IDs to be present; but the code below will then |
* execute the _REG method with the EC space ID argument. |
*/ |
NextNode = AcpiNsGetNextNode (EcDeviceNode, NULL); |
while (NextNode) |
{ |
if ((NextNode->Type == ACPI_TYPE_REGION) && |
(NextNode->Object) && |
(NextNode->Object->Region.SpaceId == ACPI_ADR_SPACE_EC)) |
{ |
goto Exit; /* Do not execute _REG */ |
} |
NextNode = AcpiNsGetNextNode (EcDeviceNode, NextNode); |
} |
/* Evaluate the _REG(EC,Connect) method */ |
Args.Count = 2; |
Args.Pointer = Objects; |
Objects[0].Type = ACPI_TYPE_INTEGER; |
Objects[0].Integer.Value = ACPI_ADR_SPACE_EC; |
Objects[1].Type = ACPI_TYPE_INTEGER; |
Objects[1].Integer.Value = ACPI_REG_CONNECT; |
Status = AcpiEvaluateObject (RegMethod, NULL, &Args, NULL); |
Exit: |
/* We ignore all errors from above, don't care */ |
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
return_VOID; |
} |
/drivers/devman/acpica/events/evrgnini.c |
---|
8,7 → 8,7 |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
395,8 → 395,8 |
} |
/* |
* Get the PCI device and function numbers from the _ADR object contained |
* in the parent's scope. |
* Get the PCI device and function numbers from the _ADR object |
* contained in the parent's scope. |
*/ |
Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, |
PciDeviceNode, &PciValue); |
429,9 → 429,14 |
PciId->Bus = ACPI_LOWORD (PciValue); |
} |
/* Complete this device's PciId */ |
/* Complete/update the PCI ID for this device */ |
AcpiOsDerivePciId (PciRootNode, RegionObj->Region.Node, &PciId); |
Status = AcpiHwDerivePciId (PciId, PciRootNode, RegionObj->Region.Node); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_FREE (PciId); |
return_ACPI_STATUS (Status); |
} |
*RegionContext = PciId; |
return_ACPI_STATUS (AE_OK); |
724,9 → 729,9 |
* |
* See AcpiNsExecModuleCode |
*/ |
if (ObjDesc->Method.Flags & AOPOBJ_MODULE_LEVEL) |
if (ObjDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) |
{ |
HandlerObj = ObjDesc->Method.Extra.Handler; |
HandlerObj = ObjDesc->Method.Dispatch.Handler; |
} |
break; |
763,7 → 768,7 |
} |
} |
Status = AcpiEvExecuteRegMethod (RegionObj, 1); |
Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_CONNECT); |
if (AcpiNsLocked) |
{ |
/drivers/devman/acpica/events/evsci.c |
---|
9,7 → 9,7 |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
/drivers/devman/acpica/events/evxface.c |
---|
8,7 → 8,7 |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
177,6 → 177,66 |
/******************************************************************************* |
* |
* FUNCTION: AcpiInstallGlobalEventHandler |
* |
* PARAMETERS: Handler - Pointer to the global event handler function |
* Context - Value passed to the handler on each event |
* |
* RETURN: Status |
* |
* DESCRIPTION: Saves the pointer to the handler function. The global handler |
* is invoked upon each incoming GPE and Fixed Event. It is |
* invoked at interrupt level at the time of the event dispatch. |
* Can be used to update event counters, etc. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiInstallGlobalEventHandler ( |
ACPI_GBL_EVENT_HANDLER Handler, |
void *Context) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler); |
/* Parameter validation */ |
if (!Handler) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* Don't allow two handlers. */ |
if (AcpiGbl_GlobalEventHandler) |
{ |
Status = AE_ALREADY_EXISTS; |
goto Cleanup; |
} |
AcpiGbl_GlobalEventHandler = Handler; |
AcpiGbl_GlobalEventHandlerContext = Context; |
Cleanup: |
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler) |
/******************************************************************************* |
* |
* FUNCTION: AcpiInstallFixedEventHandler |
* |
* PARAMETERS: Event - Event type to enable. |
691,11 → 751,11 |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber, |
UINT32 Type, |
ACPI_EVENT_HANDLER Address, |
ACPI_GPE_HANDLER Address, |
void *Context) |
{ |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_HANDLER_INFO *Handler; |
ACPI_GPE_HANDLER_INFO *Handler; |
ACPI_STATUS Status; |
ACPI_CPU_FLAGS Flags; |
716,6 → 776,17 |
return_ACPI_STATUS (Status); |
} |
/* Allocate and init handler object (before lock) */ |
Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO)); |
if (!Handler) |
{ |
Status = AE_NO_MEMORY; |
goto UnlockAndExit; |
} |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* Ensure that we have a valid GPE number */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
722,7 → 793,7 |
if (!GpeEventInfo) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
goto FreeAndExit; |
} |
/* Make sure that there isn't a handler there already */ |
731,36 → 802,40 |
ACPI_GPE_DISPATCH_HANDLER) |
{ |
Status = AE_ALREADY_EXISTS; |
goto UnlockAndExit; |
goto FreeAndExit; |
} |
/* Allocate and init handler object */ |
Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_HANDLER_INFO)); |
if (!Handler) |
{ |
Status = AE_NO_MEMORY; |
goto UnlockAndExit; |
} |
Handler->Address = Address; |
Handler->Context = Context; |
Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode; |
Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags & |
(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK)); |
/* Disable the GPE before installing the handler */ |
/* |
* If the GPE is associated with a method, it may have been enabled |
* automatically during initialization, in which case it has to be |
* disabled now to avoid spurious execution of the handler. |
*/ |
if (((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) || |
(Handler->OriginalFlags & ACPI_GPE_DISPATCH_NOTIFY)) && |
GpeEventInfo->RuntimeCount) |
{ |
Handler->OriginallyEnabled = TRUE; |
(void) AcpiEvRemoveGpeReference (GpeEventInfo); |
Status = AcpiEvDisableGpe (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
/* Sanity check of original type against new type */ |
if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK)) |
{ |
goto UnlockAndExit; |
ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)")); |
} |
} |
/* Install the handler */ |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
GpeEventInfo->Dispatch.Handler = Handler; |
/* Setup up dispatch flags to indicate handler (vs. method) */ |
/* Setup up dispatch flags to indicate handler (vs. method/notify) */ |
GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); |
GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER); |
771,6 → 846,11 |
UnlockAndExit: |
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
return_ACPI_STATUS (Status); |
FreeAndExit: |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
ACPI_FREE (Handler); |
goto UnlockAndExit; |
} |
ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler) |
795,10 → 875,10 |
AcpiRemoveGpeHandler ( |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber, |
ACPI_EVENT_HANDLER Address) |
ACPI_GPE_HANDLER Address) |
{ |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_HANDLER_INFO *Handler; |
ACPI_GPE_HANDLER_INFO *Handler; |
ACPI_STATUS Status; |
ACPI_CPU_FLAGS Flags; |
819,6 → 899,8 |
return_ACPI_STATUS (Status); |
} |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* Ensure that we have a valid GPE number */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
845,28 → 927,27 |
goto UnlockAndExit; |
} |
/* Disable the GPE before removing the handler */ |
Status = AcpiEvDisableGpe (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
goto UnlockAndExit; |
} |
/* Remove the handler */ |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
Handler = GpeEventInfo->Dispatch.Handler; |
/* Restore Method node (if any), set dispatch flags */ |
GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode; |
GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK; /* Clear bits */ |
if (Handler->MethodNode) |
GpeEventInfo->Flags &= |
~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); |
GpeEventInfo->Flags |= Handler->OriginalFlags; |
/* |
* If the GPE was previously associated with a method and it was |
* enabled, it should be enabled at this point to restore the |
* post-initialization configuration. |
*/ |
if ((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) && |
Handler->OriginallyEnabled) |
{ |
GpeEventInfo->Flags |= ACPI_GPE_DISPATCH_METHOD; |
(void) AcpiEvAddGpeReference (GpeEventInfo); |
} |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
/* Now we can free the handler object */ |
874,6 → 955,7 |
UnlockAndExit: |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
return_ACPI_STATUS (Status); |
} |
/drivers/devman/acpica/events/evxfevnt.c |
---|
8,7 → 8,7 |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
118,22 → 118,12 |
#include "acpi.h" |
#include "accommon.h" |
#include "acevents.h" |
#include "acnamesp.h" |
#include "actables.h" |
#define _COMPONENT ACPI_EVENTS |
ACPI_MODULE_NAME ("evxfevnt") |
/* Local prototypes */ |
static ACPI_STATUS |
AcpiEvGetGpeDevice ( |
ACPI_GPE_XRUPT_INFO *GpeXruptInfo, |
ACPI_GPE_BLOCK_INFO *GpeBlock, |
void *Context); |
/******************************************************************************* |
* |
* FUNCTION: AcpiEnable |
307,283 → 297,9 |
/******************************************************************************* |
* |
* FUNCTION: AcpiEnableGpe |
* |
* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 |
* GpeNumber - GPE level within the GPE block |
* GpeType - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE |
* or both |
* |
* RETURN: Status |
* |
* DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is |
* hardware-enabled (for runtime GPEs), or the GPE register mask |
* is updated (for wake GPEs). |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEnableGpe ( |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber, |
UINT8 GpeType) |
{ |
ACPI_STATUS Status = AE_OK; |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (AcpiEnableGpe); |
/* Parameter validation */ |
if (!GpeType || (GpeType & ~ACPI_GPE_TYPE_WAKE_RUN)) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* Ensure that we have a valid GPE number */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
if (!GpeEventInfo) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
if (GpeType & ACPI_GPE_TYPE_RUNTIME) |
{ |
if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX) |
{ |
Status = AE_LIMIT; /* Too many references */ |
goto UnlockAndExit; |
} |
GpeEventInfo->RuntimeCount++; |
if (GpeEventInfo->RuntimeCount == 1) |
{ |
Status = AcpiEvEnableGpe (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
GpeEventInfo->RuntimeCount--; |
goto UnlockAndExit; |
} |
} |
} |
if (GpeType & ACPI_GPE_TYPE_WAKE) |
{ |
/* The GPE must have the ability to wake the system */ |
if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) |
{ |
Status = AE_TYPE; |
goto UnlockAndExit; |
} |
if (GpeEventInfo->WakeupCount == ACPI_UINT8_MAX) |
{ |
Status = AE_LIMIT; /* Too many references */ |
goto UnlockAndExit; |
} |
/* |
* Update the enable mask on the first wakeup reference. Wake GPEs |
* are only hardware-enabled just before sleeping. |
*/ |
GpeEventInfo->WakeupCount++; |
if (GpeEventInfo->WakeupCount == 1) |
{ |
(void) AcpiEvUpdateGpeEnableMasks (GpeEventInfo); |
} |
} |
UnlockAndExit: |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiEnableGpe) |
/******************************************************************************* |
* |
* FUNCTION: AcpiDisableGpe |
* |
* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 |
* GpeNumber - GPE level within the GPE block |
* GpeType - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE |
* or both |
* |
* RETURN: Status |
* |
* DESCRIPTION: Remove a reference to a GPE. When the last reference is |
* removed, only then is the GPE disabled (for runtime GPEs), or |
* the GPE mask bit disabled (for wake GPEs) |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiDisableGpe ( |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber, |
UINT8 GpeType) |
{ |
ACPI_STATUS Status = AE_OK; |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (AcpiDisableGpe); |
/* Parameter validation */ |
if (!GpeType || (GpeType & ~ACPI_GPE_TYPE_WAKE_RUN)) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* Ensure that we have a valid GPE number */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
if (!GpeEventInfo) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* Hardware-disable a runtime GPE on removal of the last reference */ |
if (GpeType & ACPI_GPE_TYPE_RUNTIME) |
{ |
if (!GpeEventInfo->RuntimeCount) |
{ |
Status = AE_LIMIT; /* There are no references to remove */ |
goto UnlockAndExit; |
} |
GpeEventInfo->RuntimeCount--; |
if (!GpeEventInfo->RuntimeCount) |
{ |
Status = AcpiEvDisableGpe (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
GpeEventInfo->RuntimeCount++; |
goto UnlockAndExit; |
} |
} |
} |
/* |
* Update masks for wake GPE on removal of the last reference. |
* No need to hardware-disable wake GPEs here, they are not currently |
* enabled. |
*/ |
if (GpeType & ACPI_GPE_TYPE_WAKE) |
{ |
if (!GpeEventInfo->WakeupCount) |
{ |
Status = AE_LIMIT; /* There are no references to remove */ |
goto UnlockAndExit; |
} |
GpeEventInfo->WakeupCount--; |
if (!GpeEventInfo->WakeupCount) |
{ |
(void) AcpiEvUpdateGpeEnableMasks (GpeEventInfo); |
} |
} |
UnlockAndExit: |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiDisableGpe) |
/******************************************************************************* |
* |
* FUNCTION: AcpiSetGpe |
* |
* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 |
* GpeNumber - GPE level within the GPE block |
* Action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE |
* |
* RETURN: Status |
* |
* DESCRIPTION: Enable or disable an individual GPE. This function bypasses |
* the reference count mechanism used in the AcpiEnableGpe and |
* AcpiDisableGpe interfaces -- and should be used with care. |
* |
* Note: Typically used to disable a runtime GPE for short period of time, |
* then re-enable it, without disturbing the existing reference counts. This |
* is useful, for example, in the Embedded Controller (EC) driver. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiSetGpe ( |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber, |
UINT8 Action) |
{ |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_STATUS Status; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (AcpiSetGpe); |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* Ensure that we have a valid GPE number */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
if (!GpeEventInfo) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* Perform the action */ |
switch (Action) |
{ |
case ACPI_GPE_ENABLE: |
Status = AcpiEvEnableGpe (GpeEventInfo); |
break; |
case ACPI_GPE_DISABLE: |
Status = AcpiEvDisableGpe (GpeEventInfo); |
break; |
default: |
Status = AE_BAD_PARAMETER; |
break; |
} |
UnlockAndExit: |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiSetGpe) |
/******************************************************************************* |
* |
* FUNCTION: AcpiDisableEvent |
* |
* PARAMETERS: Event - The fixed eventto be enabled |
* PARAMETERS: Event - The fixed event to be disabled |
* Flags - Reserved |
* |
* RETURN: Status |
688,53 → 404,6 |
/******************************************************************************* |
* |
* FUNCTION: AcpiClearGpe |
* |
* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 |
* GpeNumber - GPE level within the GPE block |
* |
* RETURN: Status |
* |
* DESCRIPTION: Clear an ACPI event (general purpose) |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiClearGpe ( |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber) |
{ |
ACPI_STATUS Status = AE_OK; |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (AcpiClearGpe); |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* Ensure that we have a valid GPE number */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
if (!GpeEventInfo) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
Status = AcpiHwClearGpe (GpeEventInfo); |
UnlockAndExit: |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiClearGpe) |
/******************************************************************************* |
* |
* FUNCTION: AcpiGetEventStatus |
* |
* PARAMETERS: Event - The fixed event |
781,400 → 450,3 |
ACPI_EXPORT_SYMBOL (AcpiGetEventStatus) |
/******************************************************************************* |
* |
* FUNCTION: AcpiGetGpeStatus |
* |
* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 |
* GpeNumber - GPE level within the GPE block |
* EventStatus - Where the current status of the event will |
* be returned |
* |
* RETURN: Status |
* |
* DESCRIPTION: Get status of an event (general purpose) |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiGetGpeStatus ( |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber, |
ACPI_EVENT_STATUS *EventStatus) |
{ |
ACPI_STATUS Status = AE_OK; |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (AcpiGetGpeStatus); |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* Ensure that we have a valid GPE number */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
if (!GpeEventInfo) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* Obtain status on the requested GPE number */ |
Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus); |
UnlockAndExit: |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus) |
/******************************************************************************* |
* |
* FUNCTION: AcpiInstallGpeBlock |
* |
* PARAMETERS: GpeDevice - Handle to the parent GPE Block Device |
* GpeBlockAddress - Address and SpaceID |
* RegisterCount - Number of GPE register pairs in the block |
* InterruptNumber - H/W interrupt for the block |
* |
* RETURN: Status |
* |
* DESCRIPTION: Create and Install a block of GPE registers |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiInstallGpeBlock ( |
ACPI_HANDLE GpeDevice, |
ACPI_GENERIC_ADDRESS *GpeBlockAddress, |
UINT32 RegisterCount, |
UINT32 InterruptNumber) |
{ |
ACPI_STATUS Status; |
ACPI_OPERAND_OBJECT *ObjDesc; |
ACPI_NAMESPACE_NODE *Node; |
ACPI_GPE_BLOCK_INFO *GpeBlock; |
ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock); |
if ((!GpeDevice) || |
(!GpeBlockAddress) || |
(!RegisterCount)) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
if (ACPI_FAILURE (Status)) |
{ |
return (Status); |
} |
Node = AcpiNsValidateHandle (GpeDevice); |
if (!Node) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* |
* For user-installed GPE Block Devices, the GpeBlockBaseNumber |
* is always zero |
*/ |
Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress, RegisterCount, |
0, InterruptNumber, &GpeBlock); |
if (ACPI_FAILURE (Status)) |
{ |
goto UnlockAndExit; |
} |
/* Install block in the DeviceObject attached to the node */ |
ObjDesc = AcpiNsGetAttachedObject (Node); |
if (!ObjDesc) |
{ |
/* |
* No object, create a new one (Device nodes do not always have |
* an attached object) |
*/ |
ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE); |
if (!ObjDesc) |
{ |
Status = AE_NO_MEMORY; |
goto UnlockAndExit; |
} |
Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE); |
/* Remove local reference to the object */ |
AcpiUtRemoveReference (ObjDesc); |
if (ACPI_FAILURE (Status)) |
{ |
goto UnlockAndExit; |
} |
} |
/* Now install the GPE block in the DeviceObject */ |
ObjDesc->Device.GpeBlock = GpeBlock; |
/* Run the _PRW methods and enable the runtime GPEs in the new block */ |
Status = AcpiEvInitializeGpeBlock (Node, GpeBlock); |
UnlockAndExit: |
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock) |
/******************************************************************************* |
* |
* FUNCTION: AcpiRemoveGpeBlock |
* |
* PARAMETERS: GpeDevice - Handle to the parent GPE Block Device |
* |
* RETURN: Status |
* |
* DESCRIPTION: Remove a previously installed block of GPE registers |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiRemoveGpeBlock ( |
ACPI_HANDLE GpeDevice) |
{ |
ACPI_OPERAND_OBJECT *ObjDesc; |
ACPI_STATUS Status; |
ACPI_NAMESPACE_NODE *Node; |
ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock); |
if (!GpeDevice) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
if (ACPI_FAILURE (Status)) |
{ |
return (Status); |
} |
Node = AcpiNsValidateHandle (GpeDevice); |
if (!Node) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* Get the DeviceObject attached to the node */ |
ObjDesc = AcpiNsGetAttachedObject (Node); |
if (!ObjDesc || |
!ObjDesc->Device.GpeBlock) |
{ |
return_ACPI_STATUS (AE_NULL_OBJECT); |
} |
/* Delete the GPE block (but not the DeviceObject) */ |
Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock); |
if (ACPI_SUCCESS (Status)) |
{ |
ObjDesc->Device.GpeBlock = NULL; |
} |
UnlockAndExit: |
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock) |
/******************************************************************************* |
* |
* FUNCTION: AcpiGetGpeDevice |
* |
* PARAMETERS: Index - System GPE index (0-CurrentGpeCount) |
* GpeDevice - Where the parent GPE Device is returned |
* |
* RETURN: Status |
* |
* DESCRIPTION: Obtain the GPE device associated with the input index. A NULL |
* gpe device indicates that the gpe number is contained in one of |
* the FADT-defined gpe blocks. Otherwise, the GPE block device. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiGetGpeDevice ( |
UINT32 Index, |
ACPI_HANDLE *GpeDevice) |
{ |
ACPI_GPE_DEVICE_INFO Info; |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (AcpiGetGpeDevice); |
if (!GpeDevice) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
if (Index >= AcpiCurrentGpeCount) |
{ |
return_ACPI_STATUS (AE_NOT_EXIST); |
} |
/* Setup and walk the GPE list */ |
Info.Index = Index; |
Info.Status = AE_NOT_EXIST; |
Info.GpeDevice = NULL; |
Info.NextBlockBaseIndex = 0; |
Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
*GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice); |
return_ACPI_STATUS (Info.Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice) |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvGetGpeDevice |
* |
* PARAMETERS: GPE_WALK_CALLBACK |
* |
* RETURN: Status |
* |
* DESCRIPTION: Matches the input GPE index (0-CurrentGpeCount) with a GPE |
* block device. NULL if the GPE is one of the FADT-defined GPEs. |
* |
******************************************************************************/ |
static ACPI_STATUS |
AcpiEvGetGpeDevice ( |
ACPI_GPE_XRUPT_INFO *GpeXruptInfo, |
ACPI_GPE_BLOCK_INFO *GpeBlock, |
void *Context) |
{ |
ACPI_GPE_DEVICE_INFO *Info = Context; |
/* Increment Index by the number of GPEs in this block */ |
Info->NextBlockBaseIndex += GpeBlock->GpeCount; |
if (Info->Index < Info->NextBlockBaseIndex) |
{ |
/* |
* The GPE index is within this block, get the node. Leave the node |
* NULL for the FADT-defined GPEs |
*/ |
if ((GpeBlock->Node)->Type == ACPI_TYPE_DEVICE) |
{ |
Info->GpeDevice = GpeBlock->Node; |
} |
Info->Status = AE_OK; |
return (AE_CTRL_END); |
} |
return (AE_OK); |
} |
/****************************************************************************** |
* |
* FUNCTION: AcpiDisableAllGpes |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Disable and clear all GPEs in all GPE blocks |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiDisableAllGpes ( |
void) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (AcpiDisableAllGpes); |
Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
Status = AcpiHwDisableAllGpes (); |
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
return_ACPI_STATUS (Status); |
} |
/****************************************************************************** |
* |
* FUNCTION: AcpiEnableAllRuntimeGpes |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEnableAllRuntimeGpes ( |
void) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes); |
Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
Status = AcpiHwEnableAllRuntimeGpes (); |
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
return_ACPI_STATUS (Status); |
} |
/drivers/devman/acpica/events/evxfgpe.c |
---|
0,0 → 1,972 |
/****************************************************************************** |
* |
* Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs) |
* |
*****************************************************************************/ |
/****************************************************************************** |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
* |
* 2.1. This is your license from Intel Corp. under its intellectual property |
* rights. You may have additional license terms from the party that provided |
* you this software, covering your right to use that party's intellectual |
* property rights. |
* |
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a |
* copy of the source code appearing in this file ("Covered Code") an |
* irrevocable, perpetual, worldwide license under Intel's copyrights in the |
* base code distributed originally by Intel ("Original Intel Code") to copy, |
* make derivatives, distribute, use and display any portion of the Covered |
* Code in any form, with the right to sublicense such rights; and |
* |
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent |
* license (with the right to sublicense), under only those claims of Intel |
* patents that are infringed by the Original Intel Code, to make, use, sell, |
* offer to sell, and import the Covered Code and derivative works thereof |
* solely to the minimum extent necessary to exercise the above copyright |
* license, and in no event shall the patent license extend to any additions |
* to or modifications of the Original Intel Code. No other license or right |
* is granted directly or by implication, estoppel or otherwise; |
* |
* The above copyright and patent license is granted only if the following |
* conditions are met: |
* |
* 3. Conditions |
* |
* 3.1. Redistribution of Source with Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification with rights to further distribute source must include |
* the above Copyright Notice, the above License, this list of Conditions, |
* and the following Disclaimer and Export Compliance provision. In addition, |
* Licensee must cause all Covered Code to which Licensee contributes to |
* contain a file documenting the changes Licensee made to create that Covered |
* Code and the date of any change. Licensee must include in that file the |
* documentation of any changes made by any predecessor Licensee. Licensee |
* must include a prominent statement that the modification is derived, |
* directly or indirectly, from Original Intel Code. |
* |
* 3.2. Redistribution of Source with no Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification without rights to further distribute source must |
* include the following Disclaimer and Export Compliance provision in the |
* documentation and/or other materials provided with distribution. In |
* addition, Licensee may not authorize further sublicense of source of any |
* portion of the Covered Code, and must include terms to the effect that the |
* license from Licensee to its licensee is limited to the intellectual |
* property embodied in the software Licensee provides to its licensee, and |
* not to intellectual property embodied in modifications its licensee may |
* make. |
* |
* 3.3. Redistribution of Executable. Redistribution in executable form of any |
* substantial portion of the Covered Code or modification must reproduce the |
* above Copyright Notice, and the following Disclaimer and Export Compliance |
* provision in the documentation and/or other materials provided with the |
* distribution. |
* |
* 3.4. Intel retains all right, title, and interest in and to the Original |
* Intel Code. |
* |
* 3.5. Neither the name Intel nor any other trademark owned or controlled by |
* Intel shall be used in advertising or otherwise to promote the sale, use or |
* other dealings in products derived from or relating to the Covered Code |
* without prior written authorization from Intel. |
* |
* 4. Disclaimer and Export Compliance |
* |
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED |
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE |
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, |
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY |
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY |
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A |
* PARTICULAR PURPOSE. |
* |
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES |
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR |
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, |
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY |
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL |
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS |
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY |
* LIMITED REMEDY. |
* |
* 4.3. Licensee shall not export, either directly or indirectly, any of this |
* software or system incorporating such software without first obtaining any |
* required license or other approval from the U. S. Department of Commerce or |
* any other agency or department of the United States Government. In the |
* event Licensee exports any such software from the United States or |
* re-exports any such software from a foreign destination, Licensee shall |
* ensure that the distribution and export/re-export of the software is in |
* compliance with all laws, regulations, orders, or other restrictions of the |
* U.S. Export Administration Regulations. Licensee agrees that neither it nor |
* any of its subsidiaries will export/re-export any technical data, process, |
* software, or service, directly or indirectly, to any country for which the |
* United States government or any agency thereof requires an export license, |
* other governmental approval, or letter of assurance, without first obtaining |
* such license, approval or letter. |
* |
*****************************************************************************/ |
#define __EVXFGPE_C__ |
#include "acpi.h" |
#include "accommon.h" |
#include "acevents.h" |
#include "acnamesp.h" |
#define _COMPONENT ACPI_EVENTS |
ACPI_MODULE_NAME ("evxfgpe") |
/******************************************************************************* |
* |
* FUNCTION: AcpiUpdateAllGpes |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Complete GPE initialization and enable all GPEs that have |
* associated _Lxx or _Exx methods and are not pointed to by any |
* device _PRW methods (this indicates that these GPEs are |
* generally intended for system or device wakeup. Such GPEs |
* have to be enabled directly when the devices whose _PRW |
* methods point to them are set up for wakeup signaling.) |
* |
* NOTE: Should be called after any GPEs are added to the system. Primarily, |
* after the system _PRW methods have been run, but also after a GPE Block |
* Device has been added or if any new GPE methods have been added via a |
* dynamic table load. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiUpdateAllGpes ( |
void) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (AcpiUpdateGpes); |
Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
if (AcpiGbl_AllGpesInitialized) |
{ |
goto UnlockAndExit; |
} |
Status = AcpiEvWalkGpeList (AcpiEvInitializeGpeBlock, NULL); |
if (ACPI_SUCCESS (Status)) |
{ |
AcpiGbl_AllGpesInitialized = TRUE; |
} |
UnlockAndExit: |
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiUpdateAllGpes) |
/******************************************************************************* |
* |
* FUNCTION: AcpiEnableGpe |
* |
* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 |
* GpeNumber - GPE level within the GPE block |
* |
* RETURN: Status |
* |
* DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is |
* hardware-enabled. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEnableGpe ( |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber) |
{ |
ACPI_STATUS Status = AE_BAD_PARAMETER; |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (AcpiEnableGpe); |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* Ensure that we have a valid GPE number */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
if (GpeEventInfo) |
{ |
Status = AcpiEvAddGpeReference (GpeEventInfo); |
} |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiEnableGpe) |
/******************************************************************************* |
* |
* FUNCTION: AcpiDisableGpe |
* |
* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 |
* GpeNumber - GPE level within the GPE block |
* |
* RETURN: Status |
* |
* DESCRIPTION: Remove a reference to a GPE. When the last reference is |
* removed, only then is the GPE disabled (for runtime GPEs), or |
* the GPE mask bit disabled (for wake GPEs) |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiDisableGpe ( |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber) |
{ |
ACPI_STATUS Status = AE_BAD_PARAMETER; |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (AcpiDisableGpe); |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* Ensure that we have a valid GPE number */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
if (GpeEventInfo) |
{ |
Status = AcpiEvRemoveGpeReference (GpeEventInfo); |
} |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiDisableGpe) |
/******************************************************************************* |
* |
* FUNCTION: AcpiSetGpe |
* |
* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 |
* GpeNumber - GPE level within the GPE block |
* Action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE |
* |
* RETURN: Status |
* |
* DESCRIPTION: Enable or disable an individual GPE. This function bypasses |
* the reference count mechanism used in the AcpiEnableGpe and |
* AcpiDisableGpe interfaces -- and should be used with care. |
* |
* Note: Typically used to disable a runtime GPE for short period of time, |
* then re-enable it, without disturbing the existing reference counts. This |
* is useful, for example, in the Embedded Controller (EC) driver. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiSetGpe ( |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber, |
UINT8 Action) |
{ |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_STATUS Status; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (AcpiSetGpe); |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* Ensure that we have a valid GPE number */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
if (!GpeEventInfo) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* Perform the action */ |
switch (Action) |
{ |
case ACPI_GPE_ENABLE: |
Status = AcpiEvEnableGpe (GpeEventInfo); |
break; |
case ACPI_GPE_DISABLE: |
Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); |
break; |
default: |
Status = AE_BAD_PARAMETER; |
break; |
} |
UnlockAndExit: |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiSetGpe) |
/******************************************************************************* |
* |
* FUNCTION: AcpiSetupGpeForWake |
* |
* PARAMETERS: WakeDevice - Device associated with the GPE (via _PRW) |
* GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 |
* GpeNumber - GPE level within the GPE block |
* |
* RETURN: Status |
* |
* DESCRIPTION: Mark a GPE as having the ability to wake the system. This |
* interface is intended to be used as the host executes the |
* _PRW methods (Power Resources for Wake) in the system tables. |
* Each _PRW appears under a Device Object (The WakeDevice), and |
* contains the info for the wake GPE associated with the |
* WakeDevice. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiSetupGpeForWake ( |
ACPI_HANDLE WakeDevice, |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber) |
{ |
ACPI_STATUS Status = AE_BAD_PARAMETER; |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_NAMESPACE_NODE *DeviceNode; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake); |
/* Parameter Validation */ |
if (!WakeDevice) |
{ |
/* |
* By forcing WakeDevice to be valid, we automatically enable the |
* implicit notify feature on all hosts. |
*/ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
/* Handle root object case */ |
if (WakeDevice == ACPI_ROOT_OBJECT) |
{ |
DeviceNode = AcpiGbl_RootNode; |
} |
else |
{ |
DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice); |
} |
/* Validate WakeDevice is of type Device */ |
if (DeviceNode->Type != ACPI_TYPE_DEVICE) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* Ensure that we have a valid GPE number */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
if (GpeEventInfo) |
{ |
/* |
* If there is no method or handler for this GPE, then the |
* WakeDevice will be notified whenever this GPE fires (aka |
* "implicit notify") Note: The GPE is assumed to be |
* level-triggered (for windows compatibility). |
*/ |
if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == |
ACPI_GPE_DISPATCH_NONE) |
{ |
GpeEventInfo->Flags = |
(ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED); |
GpeEventInfo->Dispatch.DeviceNode = DeviceNode; |
} |
GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; |
Status = AE_OK; |
} |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake) |
/******************************************************************************* |
* |
* FUNCTION: AcpiSetGpeWakeMask |
* |
* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 |
* GpeNumber - GPE level within the GPE block |
* Action - Enable or Disable |
* |
* RETURN: Status |
* |
* DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must |
* already be marked as a WAKE GPE. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiSetGpeWakeMask ( |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber, |
UINT8 Action) |
{ |
ACPI_STATUS Status = AE_OK; |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; |
ACPI_CPU_FLAGS Flags; |
UINT32 RegisterBit; |
ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask); |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* |
* Ensure that we have a valid GPE number and that this GPE is in |
* fact a wake GPE |
*/ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
if (!GpeEventInfo) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) |
{ |
Status = AE_TYPE; |
goto UnlockAndExit; |
} |
GpeRegisterInfo = GpeEventInfo->RegisterInfo; |
if (!GpeRegisterInfo) |
{ |
Status = AE_NOT_EXIST; |
goto UnlockAndExit; |
} |
RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo); |
/* Perform the action */ |
switch (Action) |
{ |
case ACPI_GPE_ENABLE: |
ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit); |
break; |
case ACPI_GPE_DISABLE: |
ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit); |
break; |
default: |
ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action)); |
Status = AE_BAD_PARAMETER; |
break; |
} |
UnlockAndExit: |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask) |
/******************************************************************************* |
* |
* FUNCTION: AcpiClearGpe |
* |
* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 |
* GpeNumber - GPE level within the GPE block |
* |
* RETURN: Status |
* |
* DESCRIPTION: Clear an ACPI event (general purpose) |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiClearGpe ( |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber) |
{ |
ACPI_STATUS Status = AE_OK; |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (AcpiClearGpe); |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* Ensure that we have a valid GPE number */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
if (!GpeEventInfo) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
Status = AcpiHwClearGpe (GpeEventInfo); |
UnlockAndExit: |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiClearGpe) |
/******************************************************************************* |
* |
* FUNCTION: AcpiGetGpeStatus |
* |
* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 |
* GpeNumber - GPE level within the GPE block |
* EventStatus - Where the current status of the event |
* will be returned |
* |
* RETURN: Status |
* |
* DESCRIPTION: Get the current status of a GPE (signalled/not_signalled) |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiGetGpeStatus ( |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber, |
ACPI_EVENT_STATUS *EventStatus) |
{ |
ACPI_STATUS Status = AE_OK; |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (AcpiGetGpeStatus); |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* Ensure that we have a valid GPE number */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
if (!GpeEventInfo) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* Obtain status on the requested GPE number */ |
Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus); |
UnlockAndExit: |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus) |
/******************************************************************************* |
* |
* FUNCTION: AcpiFinishGpe |
* |
* PARAMETERS: GpeDevice - Namespace node for the GPE Block |
* (NULL for FADT defined GPEs) |
* GpeNumber - GPE level within the GPE block |
* |
* RETURN: Status |
* |
* DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE |
* processing. Intended for use by asynchronous host-installed |
* GPE handlers. The GPE is only reenabled if the EnableForRun bit |
* is set in the GPE info. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiFinishGpe ( |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber) |
{ |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_STATUS Status; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (AcpiFinishGpe); |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* Ensure that we have a valid GPE number */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
if (!GpeEventInfo) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
Status = AcpiEvFinishGpe (GpeEventInfo); |
UnlockAndExit: |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiFinishGpe) |
/****************************************************************************** |
* |
* FUNCTION: AcpiDisableAllGpes |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Disable and clear all GPEs in all GPE blocks |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiDisableAllGpes ( |
void) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (AcpiDisableAllGpes); |
Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
Status = AcpiHwDisableAllGpes (); |
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes) |
/****************************************************************************** |
* |
* FUNCTION: AcpiEnableAllRuntimeGpes |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEnableAllRuntimeGpes ( |
void) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes); |
Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
Status = AcpiHwEnableAllRuntimeGpes (); |
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes) |
/******************************************************************************* |
* |
* FUNCTION: AcpiInstallGpeBlock |
* |
* PARAMETERS: GpeDevice - Handle to the parent GPE Block Device |
* GpeBlockAddress - Address and SpaceID |
* RegisterCount - Number of GPE register pairs in the block |
* InterruptNumber - H/W interrupt for the block |
* |
* RETURN: Status |
* |
* DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not |
* enabled here. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiInstallGpeBlock ( |
ACPI_HANDLE GpeDevice, |
ACPI_GENERIC_ADDRESS *GpeBlockAddress, |
UINT32 RegisterCount, |
UINT32 InterruptNumber) |
{ |
ACPI_STATUS Status; |
ACPI_OPERAND_OBJECT *ObjDesc; |
ACPI_NAMESPACE_NODE *Node; |
ACPI_GPE_BLOCK_INFO *GpeBlock; |
ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock); |
if ((!GpeDevice) || |
(!GpeBlockAddress) || |
(!RegisterCount)) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
if (ACPI_FAILURE (Status)) |
{ |
return (Status); |
} |
Node = AcpiNsValidateHandle (GpeDevice); |
if (!Node) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* |
* For user-installed GPE Block Devices, the GpeBlockBaseNumber |
* is always zero |
*/ |
Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress, RegisterCount, |
0, InterruptNumber, &GpeBlock); |
if (ACPI_FAILURE (Status)) |
{ |
goto UnlockAndExit; |
} |
/* Install block in the DeviceObject attached to the node */ |
ObjDesc = AcpiNsGetAttachedObject (Node); |
if (!ObjDesc) |
{ |
/* |
* No object, create a new one (Device nodes do not always have |
* an attached object) |
*/ |
ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE); |
if (!ObjDesc) |
{ |
Status = AE_NO_MEMORY; |
goto UnlockAndExit; |
} |
Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE); |
/* Remove local reference to the object */ |
AcpiUtRemoveReference (ObjDesc); |
if (ACPI_FAILURE (Status)) |
{ |
goto UnlockAndExit; |
} |
} |
/* Now install the GPE block in the DeviceObject */ |
ObjDesc->Device.GpeBlock = GpeBlock; |
UnlockAndExit: |
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock) |
/******************************************************************************* |
* |
* FUNCTION: AcpiRemoveGpeBlock |
* |
* PARAMETERS: GpeDevice - Handle to the parent GPE Block Device |
* |
* RETURN: Status |
* |
* DESCRIPTION: Remove a previously installed block of GPE registers |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiRemoveGpeBlock ( |
ACPI_HANDLE GpeDevice) |
{ |
ACPI_OPERAND_OBJECT *ObjDesc; |
ACPI_STATUS Status; |
ACPI_NAMESPACE_NODE *Node; |
ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock); |
if (!GpeDevice) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
if (ACPI_FAILURE (Status)) |
{ |
return (Status); |
} |
Node = AcpiNsValidateHandle (GpeDevice); |
if (!Node) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* Get the DeviceObject attached to the node */ |
ObjDesc = AcpiNsGetAttachedObject (Node); |
if (!ObjDesc || |
!ObjDesc->Device.GpeBlock) |
{ |
return_ACPI_STATUS (AE_NULL_OBJECT); |
} |
/* Delete the GPE block (but not the DeviceObject) */ |
Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock); |
if (ACPI_SUCCESS (Status)) |
{ |
ObjDesc->Device.GpeBlock = NULL; |
} |
UnlockAndExit: |
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock) |
/******************************************************************************* |
* |
* FUNCTION: AcpiGetGpeDevice |
* |
* PARAMETERS: Index - System GPE index (0-CurrentGpeCount) |
* GpeDevice - Where the parent GPE Device is returned |
* |
* RETURN: Status |
* |
* DESCRIPTION: Obtain the GPE device associated with the input index. A NULL |
* gpe device indicates that the gpe number is contained in one of |
* the FADT-defined gpe blocks. Otherwise, the GPE block device. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiGetGpeDevice ( |
UINT32 Index, |
ACPI_HANDLE *GpeDevice) |
{ |
ACPI_GPE_DEVICE_INFO Info; |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (AcpiGetGpeDevice); |
if (!GpeDevice) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
if (Index >= AcpiCurrentGpeCount) |
{ |
return_ACPI_STATUS (AE_NOT_EXIST); |
} |
/* Setup and walk the GPE list */ |
Info.Index = Index; |
Info.Status = AE_NOT_EXIST; |
Info.GpeDevice = NULL; |
Info.NextBlockBaseIndex = 0; |
Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
*GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice); |
return_ACPI_STATUS (Info.Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice) |
/drivers/devman/acpica/events/evxfregn.c |
---|
9,7 → 9,7 |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
139,6 → 139,12 |
* |
* DESCRIPTION: Install a handler for all OpRegions of a given SpaceId. |
* |
* NOTE: This function should only be called after AcpiEnableSubsystem has |
* been called. This is because any _REG methods associated with the Space ID |
* are executed here, and these methods can only be safely executed after |
* the default handlers have been installed and the hardware has been |
* initialized (via AcpiEnableSubsystem.) |
* |
******************************************************************************/ |
ACPI_STATUS |
186,10 → 192,43 |
goto UnlockAndExit; |
} |
/* |
* For the default SpaceIDs, (the IDs for which there are default region handlers |
* installed) Only execute the _REG methods if the global initialization _REG |
* methods have already been run (via AcpiInitializeObjects). In other words, |
* we will defer the execution of the _REG methods for these SpaceIDs until |
* execution of AcpiInitializeObjects. This is done because we need the handlers |
* for the default spaces (mem/io/pci/table) to be installed before we can run |
* any control methods (or _REG methods). There is known BIOS code that depends |
* on this. |
* |
* For all other SpaceIDs, we can safely execute the _REG methods immediately. |
* This means that for IDs like EmbeddedController, this function should be called |
* only after AcpiEnableSubsystem has been called. |
*/ |
switch (SpaceId) |
{ |
case ACPI_ADR_SPACE_SYSTEM_MEMORY: |
case ACPI_ADR_SPACE_SYSTEM_IO: |
case ACPI_ADR_SPACE_PCI_CONFIG: |
case ACPI_ADR_SPACE_DATA_TABLE: |
if (!AcpiGbl_RegMethodsExecuted) |
{ |
/* We will defer execution of the _REG methods for this space */ |
goto UnlockAndExit; |
} |
break; |
default: |
break; |
} |
/* Run all _REG methods for this address space */ |
Status = AcpiEvExecuteRegMethods (Node, SpaceId); |
UnlockAndExit: |
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
return_ACPI_STATUS (Status); |