Home | History | Annotate | Line # | Download | only in events
evgpeutil.c revision 1.1
      1 /******************************************************************************
      2  *
      3  * Module Name: evgpeutil - GPE utilities
      4  *
      5  *****************************************************************************/
      6 
      7 /******************************************************************************
      8  *
      9  * 1. Copyright Notice
     10  *
     11  * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
     12  * All rights reserved.
     13  *
     14  * 2. License
     15  *
     16  * 2.1. This is your license from Intel Corp. under its intellectual property
     17  * rights.  You may have additional license terms from the party that provided
     18  * you this software, covering your right to use that party's intellectual
     19  * property rights.
     20  *
     21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
     22  * copy of the source code appearing in this file ("Covered Code") an
     23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
     24  * base code distributed originally by Intel ("Original Intel Code") to copy,
     25  * make derivatives, distribute, use and display any portion of the Covered
     26  * Code in any form, with the right to sublicense such rights; and
     27  *
     28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
     29  * license (with the right to sublicense), under only those claims of Intel
     30  * patents that are infringed by the Original Intel Code, to make, use, sell,
     31  * offer to sell, and import the Covered Code and derivative works thereof
     32  * solely to the minimum extent necessary to exercise the above copyright
     33  * license, and in no event shall the patent license extend to any additions
     34  * to or modifications of the Original Intel Code.  No other license or right
     35  * is granted directly or by implication, estoppel or otherwise;
     36  *
     37  * The above copyright and patent license is granted only if the following
     38  * conditions are met:
     39  *
     40  * 3. Conditions
     41  *
     42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
     43  * Redistribution of source code of any substantial portion of the Covered
     44  * Code or modification with rights to further distribute source must include
     45  * the above Copyright Notice, the above License, this list of Conditions,
     46  * and the following Disclaimer and Export Compliance provision.  In addition,
     47  * Licensee must cause all Covered Code to which Licensee contributes to
     48  * contain a file documenting the changes Licensee made to create that Covered
     49  * Code and the date of any change.  Licensee must include in that file the
     50  * documentation of any changes made by any predecessor Licensee.  Licensee
     51  * must include a prominent statement that the modification is derived,
     52  * directly or indirectly, from Original Intel Code.
     53  *
     54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
     55  * Redistribution of source code of any substantial portion of the Covered
     56  * Code or modification without rights to further distribute source must
     57  * include the following Disclaimer and Export Compliance provision in the
     58  * documentation and/or other materials provided with distribution.  In
     59  * addition, Licensee may not authorize further sublicense of source of any
     60  * portion of the Covered Code, and must include terms to the effect that the
     61  * license from Licensee to its licensee is limited to the intellectual
     62  * property embodied in the software Licensee provides to its licensee, and
     63  * not to intellectual property embodied in modifications its licensee may
     64  * make.
     65  *
     66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
     67  * substantial portion of the Covered Code or modification must reproduce the
     68  * above Copyright Notice, and the following Disclaimer and Export Compliance
     69  * provision in the documentation and/or other materials provided with the
     70  * distribution.
     71  *
     72  * 3.4. Intel retains all right, title, and interest in and to the Original
     73  * Intel Code.
     74  *
     75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
     76  * Intel shall be used in advertising or otherwise to promote the sale, use or
     77  * other dealings in products derived from or relating to the Covered Code
     78  * without prior written authorization from Intel.
     79  *
     80  * 4. Disclaimer and Export Compliance
     81  *
     82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
     83  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
     84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
     85  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
     86  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
     87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
     88  * PARTICULAR PURPOSE.
     89  *
     90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
     91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
     92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
     93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
     94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
     95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
     96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
     97  * LIMITED REMEDY.
     98  *
     99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
    100  * software or system incorporating such software without first obtaining any
    101  * required license or other approval from the U. S. Department of Commerce or
    102  * any other agency or department of the United States Government.  In the
    103  * event Licensee exports any such software from the United States or
    104  * re-exports any such software from a foreign destination, Licensee shall
    105  * ensure that the distribution and export/re-export of the software is in
    106  * compliance with all laws, regulations, orders, or other restrictions of the
    107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
    108  * any of its subsidiaries will export/re-export any technical data, process,
    109  * software, or service, directly or indirectly, to any country for which the
    110  * United States government or any agency thereof requires an export license,
    111  * other governmental approval, or letter of assurance, without first obtaining
    112  * such license, approval or letter.
    113  *
    114  *****************************************************************************/
    115 
    116 
    117 #include "acpi.h"
    118 #include "accommon.h"
    119 #include "acevents.h"
    120 
    121 #define _COMPONENT          ACPI_EVENTS
    122         ACPI_MODULE_NAME    ("evgpeutil")
    123 
    124 
    125 /*******************************************************************************
    126  *
    127  * FUNCTION:    AcpiEvWalkGpeList
    128  *
    129  * PARAMETERS:  GpeWalkCallback     - Routine called for each GPE block
    130  *              Context             - Value passed to callback
    131  *
    132  * RETURN:      Status
    133  *
    134  * DESCRIPTION: Walk the GPE lists.
    135  *
    136  ******************************************************************************/
    137 
    138 ACPI_STATUS
    139 AcpiEvWalkGpeList (
    140     ACPI_GPE_CALLBACK       GpeWalkCallback,
    141     void                    *Context)
    142 {
    143     ACPI_GPE_BLOCK_INFO     *GpeBlock;
    144     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo;
    145     ACPI_STATUS             Status = AE_OK;
    146     ACPI_CPU_FLAGS          Flags;
    147 
    148 
    149     ACPI_FUNCTION_TRACE (EvWalkGpeList);
    150 
    151 
    152     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    153 
    154     /* Walk the interrupt level descriptor list */
    155 
    156     GpeXruptInfo = AcpiGbl_GpeXruptListHead;
    157     while (GpeXruptInfo)
    158     {
    159         /* Walk all Gpe Blocks attached to this interrupt level */
    160 
    161         GpeBlock = GpeXruptInfo->GpeBlockListHead;
    162         while (GpeBlock)
    163         {
    164             /* One callback per GPE block */
    165 
    166             Status = GpeWalkCallback (GpeXruptInfo, GpeBlock, Context);
    167             if (ACPI_FAILURE (Status))
    168             {
    169                 if (Status == AE_CTRL_END) /* Callback abort */
    170                 {
    171                     Status = AE_OK;
    172                 }
    173                 goto UnlockAndExit;
    174             }
    175 
    176             GpeBlock = GpeBlock->Next;
    177         }
    178 
    179         GpeXruptInfo = GpeXruptInfo->Next;
    180     }
    181 
    182 UnlockAndExit:
    183     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    184     return_ACPI_STATUS (Status);
    185 }
    186 
    187 
    188 /*******************************************************************************
    189  *
    190  * FUNCTION:    AcpiEvValidGpeEvent
    191  *
    192  * PARAMETERS:  GpeEventInfo                - Info for this GPE
    193  *
    194  * RETURN:      TRUE if the GpeEvent is valid
    195  *
    196  * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL.
    197  *              Should be called only when the GPE lists are semaphore locked
    198  *              and not subject to change.
    199  *
    200  ******************************************************************************/
    201 
    202 BOOLEAN
    203 AcpiEvValidGpeEvent (
    204     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
    205 {
    206     ACPI_GPE_XRUPT_INFO     *GpeXruptBlock;
    207     ACPI_GPE_BLOCK_INFO     *GpeBlock;
    208 
    209 
    210     ACPI_FUNCTION_ENTRY ();
    211 
    212 
    213     /* No need for spin lock since we are not changing any list elements */
    214 
    215     /* Walk the GPE interrupt levels */
    216 
    217     GpeXruptBlock = AcpiGbl_GpeXruptListHead;
    218     while (GpeXruptBlock)
    219     {
    220         GpeBlock = GpeXruptBlock->GpeBlockListHead;
    221 
    222         /* Walk the GPE blocks on this interrupt level */
    223 
    224         while (GpeBlock)
    225         {
    226             if ((&GpeBlock->EventInfo[0] <= GpeEventInfo) &&
    227                 (&GpeBlock->EventInfo[GpeBlock->GpeCount] > GpeEventInfo))
    228             {
    229                 return (TRUE);
    230             }
    231 
    232             GpeBlock = GpeBlock->Next;
    233         }
    234 
    235         GpeXruptBlock = GpeXruptBlock->Next;
    236     }
    237 
    238     return (FALSE);
    239 }
    240 
    241 
    242 /*******************************************************************************
    243  *
    244  * FUNCTION:    AcpiEvGetGpeXruptBlock
    245  *
    246  * PARAMETERS:  InterruptNumber      - Interrupt for a GPE block
    247  *
    248  * RETURN:      A GPE interrupt block
    249  *
    250  * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt
    251  *              block per unique interrupt level used for GPEs. Should be
    252  *              called only when the GPE lists are semaphore locked and not
    253  *              subject to change.
    254  *
    255  ******************************************************************************/
    256 
    257 ACPI_GPE_XRUPT_INFO *
    258 AcpiEvGetGpeXruptBlock (
    259     UINT32                  InterruptNumber)
    260 {
    261     ACPI_GPE_XRUPT_INFO     *NextGpeXrupt;
    262     ACPI_GPE_XRUPT_INFO     *GpeXrupt;
    263     ACPI_STATUS             Status;
    264     ACPI_CPU_FLAGS          Flags;
    265 
    266 
    267     ACPI_FUNCTION_TRACE (EvGetGpeXruptBlock);
    268 
    269 
    270     /* No need for lock since we are not changing any list elements here */
    271 
    272     NextGpeXrupt = AcpiGbl_GpeXruptListHead;
    273     while (NextGpeXrupt)
    274     {
    275         if (NextGpeXrupt->InterruptNumber == InterruptNumber)
    276         {
    277             return_PTR (NextGpeXrupt);
    278         }
    279 
    280         NextGpeXrupt = NextGpeXrupt->Next;
    281     }
    282 
    283     /* Not found, must allocate a new xrupt descriptor */
    284 
    285     GpeXrupt = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_XRUPT_INFO));
    286     if (!GpeXrupt)
    287     {
    288         return_PTR (NULL);
    289     }
    290 
    291     GpeXrupt->InterruptNumber = InterruptNumber;
    292 
    293     /* Install new interrupt descriptor with spin lock */
    294 
    295     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    296     if (AcpiGbl_GpeXruptListHead)
    297     {
    298         NextGpeXrupt = AcpiGbl_GpeXruptListHead;
    299         while (NextGpeXrupt->Next)
    300         {
    301             NextGpeXrupt = NextGpeXrupt->Next;
    302         }
    303 
    304         NextGpeXrupt->Next = GpeXrupt;
    305         GpeXrupt->Previous = NextGpeXrupt;
    306     }
    307     else
    308     {
    309         AcpiGbl_GpeXruptListHead = GpeXrupt;
    310     }
    311     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    312 
    313     /* Install new interrupt handler if not SCI_INT */
    314 
    315     if (InterruptNumber != AcpiGbl_FADT.SciInterrupt)
    316     {
    317         Status = AcpiOsInstallInterruptHandler (InterruptNumber,
    318                     AcpiEvGpeXruptHandler, GpeXrupt);
    319         if (ACPI_FAILURE (Status))
    320         {
    321             ACPI_ERROR ((AE_INFO,
    322                 "Could not install GPE interrupt handler at level 0x%X",
    323                 InterruptNumber));
    324             return_PTR (NULL);
    325         }
    326     }
    327 
    328     return_PTR (GpeXrupt);
    329 }
    330 
    331 
    332 /*******************************************************************************
    333  *
    334  * FUNCTION:    AcpiEvDeleteGpeXrupt
    335  *
    336  * PARAMETERS:  GpeXrupt        - A GPE interrupt info block
    337  *
    338  * RETURN:      Status
    339  *
    340  * DESCRIPTION: Remove and free a GpeXrupt block. Remove an associated
    341  *              interrupt handler if not the SCI interrupt.
    342  *
    343  ******************************************************************************/
    344 
    345 ACPI_STATUS
    346 AcpiEvDeleteGpeXrupt (
    347     ACPI_GPE_XRUPT_INFO     *GpeXrupt)
    348 {
    349     ACPI_STATUS             Status;
    350     ACPI_CPU_FLAGS          Flags;
    351 
    352 
    353     ACPI_FUNCTION_TRACE (EvDeleteGpeXrupt);
    354 
    355 
    356     /* We never want to remove the SCI interrupt handler */
    357 
    358     if (GpeXrupt->InterruptNumber == AcpiGbl_FADT.SciInterrupt)
    359     {
    360         GpeXrupt->GpeBlockListHead = NULL;
    361         return_ACPI_STATUS (AE_OK);
    362     }
    363 
    364     /* Disable this interrupt */
    365 
    366     Status = AcpiOsRemoveInterruptHandler (
    367                 GpeXrupt->InterruptNumber, AcpiEvGpeXruptHandler);
    368     if (ACPI_FAILURE (Status))
    369     {
    370         return_ACPI_STATUS (Status);
    371     }
    372 
    373     /* Unlink the interrupt block with lock */
    374 
    375     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    376     if (GpeXrupt->Previous)
    377     {
    378         GpeXrupt->Previous->Next = GpeXrupt->Next;
    379     }
    380     else
    381     {
    382         /* No previous, update list head */
    383 
    384         AcpiGbl_GpeXruptListHead = GpeXrupt->Next;
    385     }
    386 
    387     if (GpeXrupt->Next)
    388     {
    389         GpeXrupt->Next->Previous = GpeXrupt->Previous;
    390     }
    391     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    392 
    393     /* Free the block */
    394 
    395     ACPI_FREE (GpeXrupt);
    396     return_ACPI_STATUS (AE_OK);
    397 }
    398 
    399 
    400 /*******************************************************************************
    401  *
    402  * FUNCTION:    AcpiEvDeleteGpeHandlers
    403  *
    404  * PARAMETERS:  GpeXruptInfo        - GPE Interrupt info
    405  *              GpeBlock            - Gpe Block info
    406  *
    407  * RETURN:      Status
    408  *
    409  * DESCRIPTION: Delete all Handler objects found in the GPE data structs.
    410  *              Used only prior to termination.
    411  *
    412  ******************************************************************************/
    413 
    414 ACPI_STATUS
    415 AcpiEvDeleteGpeHandlers (
    416     ACPI_GPE_XRUPT_INFO     *GpeXruptInfo,
    417     ACPI_GPE_BLOCK_INFO     *GpeBlock,
    418     void                    *Context)
    419 {
    420     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
    421     UINT32                  i;
    422     UINT32                  j;
    423 
    424 
    425     ACPI_FUNCTION_TRACE (EvDeleteGpeHandlers);
    426 
    427 
    428     /* Examine each GPE Register within the block */
    429 
    430     for (i = 0; i < GpeBlock->RegisterCount; i++)
    431     {
    432         /* Now look at the individual GPEs in this byte register */
    433 
    434         for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
    435         {
    436             GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i *
    437                 ACPI_GPE_REGISTER_WIDTH) + j];
    438 
    439             if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
    440                     ACPI_GPE_DISPATCH_HANDLER)
    441             {
    442                 ACPI_FREE (GpeEventInfo->Dispatch.Handler);
    443                 GpeEventInfo->Dispatch.Handler = NULL;
    444                 GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK;
    445             }
    446         }
    447     }
    448 
    449     return_ACPI_STATUS (AE_OK);
    450 }
    451 
    452