Home | History | Annotate | Line # | Download | only in events
evmisc.c revision 1.1.1.7
      1 /******************************************************************************
      2  *
      3  * Module Name: evmisc - Miscellaneous event manager support functions
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2016, Intel Corp.
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions, and the following disclaimer,
     16  *    without modification.
     17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     18  *    substantially similar to the "NO WARRANTY" disclaimer below
     19  *    ("Disclaimer") and any redistribution must be conditioned upon
     20  *    including a substantially similar Disclaimer requirement for further
     21  *    binary redistribution.
     22  * 3. Neither the names of the above-listed copyright holders nor the names
     23  *    of any contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * Alternatively, this software may be distributed under the terms of the
     27  * GNU General Public License ("GPL") version 2 as published by the Free
     28  * Software Foundation.
     29  *
     30  * NO WARRANTY
     31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
     34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     41  * POSSIBILITY OF SUCH DAMAGES.
     42  */
     43 
     44 #include "acpi.h"
     45 #include "accommon.h"
     46 #include "acevents.h"
     47 #include "acnamesp.h"
     48 
     49 #define _COMPONENT          ACPI_EVENTS
     50         ACPI_MODULE_NAME    ("evmisc")
     51 
     52 
     53 /* Local prototypes */
     54 
     55 static void ACPI_SYSTEM_XFACE
     56 AcpiEvNotifyDispatch (
     57     void                    *Context);
     58 
     59 
     60 /*******************************************************************************
     61  *
     62  * FUNCTION:    AcpiEvIsNotifyObject
     63  *
     64  * PARAMETERS:  Node            - Node to check
     65  *
     66  * RETURN:      TRUE if notifies allowed on this object
     67  *
     68  * DESCRIPTION: Check type of node for a object that supports notifies.
     69  *
     70  *              TBD: This could be replaced by a flag bit in the node.
     71  *
     72  ******************************************************************************/
     73 
     74 BOOLEAN
     75 AcpiEvIsNotifyObject (
     76     ACPI_NAMESPACE_NODE     *Node)
     77 {
     78 
     79     switch (Node->Type)
     80     {
     81     case ACPI_TYPE_DEVICE:
     82     case ACPI_TYPE_PROCESSOR:
     83     case ACPI_TYPE_THERMAL:
     84         /*
     85          * These are the ONLY objects that can receive ACPI notifications
     86          */
     87         return (TRUE);
     88 
     89     default:
     90 
     91         return (FALSE);
     92     }
     93 }
     94 
     95 
     96 /*******************************************************************************
     97  *
     98  * FUNCTION:    AcpiEvQueueNotifyRequest
     99  *
    100  * PARAMETERS:  Node            - NS node for the notified object
    101  *              NotifyValue     - Value from the Notify() request
    102  *
    103  * RETURN:      Status
    104  *
    105  * DESCRIPTION: Dispatch a device notification event to a previously
    106  *              installed handler.
    107  *
    108  ******************************************************************************/
    109 
    110 ACPI_STATUS
    111 AcpiEvQueueNotifyRequest (
    112     ACPI_NAMESPACE_NODE     *Node,
    113     UINT32                  NotifyValue)
    114 {
    115     ACPI_OPERAND_OBJECT     *ObjDesc;
    116     ACPI_OPERAND_OBJECT     *HandlerListHead = NULL;
    117     ACPI_GENERIC_STATE      *Info;
    118     UINT8                   HandlerListId = 0;
    119     ACPI_STATUS             Status = AE_OK;
    120 
    121 
    122     ACPI_FUNCTION_NAME (EvQueueNotifyRequest);
    123 
    124 
    125     /* Are Notifies allowed on this object? */
    126 
    127     if (!AcpiEvIsNotifyObject (Node))
    128     {
    129         return (AE_TYPE);
    130     }
    131 
    132     /* Get the correct notify list type (System or Device) */
    133 
    134     if (NotifyValue <= ACPI_MAX_SYS_NOTIFY)
    135     {
    136         HandlerListId = ACPI_SYSTEM_HANDLER_LIST;
    137     }
    138     else
    139     {
    140         HandlerListId = ACPI_DEVICE_HANDLER_LIST;
    141     }
    142 
    143     /* Get the notify object attached to the namespace Node */
    144 
    145     ObjDesc = AcpiNsGetAttachedObject (Node);
    146     if (ObjDesc)
    147     {
    148         /* We have an attached object, Get the correct handler list */
    149 
    150         HandlerListHead = ObjDesc->CommonNotify.NotifyList[HandlerListId];
    151     }
    152 
    153     /*
    154      * If there is no notify handler (Global or Local)
    155      * for this object, just ignore the notify
    156      */
    157     if (!AcpiGbl_GlobalNotify[HandlerListId].Handler && !HandlerListHead)
    158     {
    159         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
    160             "No notify handler for Notify, ignoring (%4.4s, %X) node %p\n",
    161             AcpiUtGetNodeName (Node), NotifyValue, Node));
    162 
    163         return (AE_OK);
    164     }
    165 
    166     /* Setup notify info and schedule the notify dispatcher */
    167 
    168     Info = AcpiUtCreateGenericState ();
    169     if (!Info)
    170     {
    171         return (AE_NO_MEMORY);
    172     }
    173 
    174     Info->Common.DescriptorType = ACPI_DESC_TYPE_STATE_NOTIFY;
    175 
    176     Info->Notify.Node = Node;
    177     Info->Notify.Value = (UINT16) NotifyValue;
    178     Info->Notify.HandlerListId = HandlerListId;
    179     Info->Notify.HandlerListHead = HandlerListHead;
    180     Info->Notify.Global = &AcpiGbl_GlobalNotify[HandlerListId];
    181 
    182     ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
    183         "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n",
    184         AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type),
    185         NotifyValue, AcpiUtGetNotifyName (NotifyValue, ACPI_TYPE_ANY), Node));
    186 
    187     Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
    188         AcpiEvNotifyDispatch, Info);
    189     if (ACPI_FAILURE (Status))
    190     {
    191         AcpiUtDeleteGenericState (Info);
    192     }
    193 
    194     return (Status);
    195 }
    196 
    197 
    198 /*******************************************************************************
    199  *
    200  * FUNCTION:    AcpiEvNotifyDispatch
    201  *
    202  * PARAMETERS:  Context         - To be passed to the notify handler
    203  *
    204  * RETURN:      None.
    205  *
    206  * DESCRIPTION: Dispatch a device notification event to a previously
    207  *              installed handler.
    208  *
    209  ******************************************************************************/
    210 
    211 static void ACPI_SYSTEM_XFACE
    212 AcpiEvNotifyDispatch (
    213     void                    *Context)
    214 {
    215     ACPI_GENERIC_STATE      *Info = (ACPI_GENERIC_STATE *) Context;
    216     ACPI_OPERAND_OBJECT     *HandlerObj;
    217 
    218 
    219     ACPI_FUNCTION_ENTRY ();
    220 
    221 
    222     /* Invoke a global notify handler if installed */
    223 
    224     if (Info->Notify.Global->Handler)
    225     {
    226         Info->Notify.Global->Handler (Info->Notify.Node,
    227             Info->Notify.Value,
    228             Info->Notify.Global->Context);
    229     }
    230 
    231     /* Now invoke the local notify handler(s) if any are installed */
    232 
    233     HandlerObj = Info->Notify.HandlerListHead;
    234     while (HandlerObj)
    235     {
    236         HandlerObj->Notify.Handler (Info->Notify.Node,
    237             Info->Notify.Value,
    238             HandlerObj->Notify.Context);
    239 
    240         HandlerObj = HandlerObj->Notify.Next[Info->Notify.HandlerListId];
    241     }
    242 
    243     /* All done with the info object */
    244 
    245     AcpiUtDeleteGenericState (Info);
    246 }
    247 
    248 
    249 #if (!ACPI_REDUCED_HARDWARE)
    250 /******************************************************************************
    251  *
    252  * FUNCTION:    AcpiEvTerminate
    253  *
    254  * PARAMETERS:  none
    255  *
    256  * RETURN:      none
    257  *
    258  * DESCRIPTION: Disable events and free memory allocated for table storage.
    259  *
    260  ******************************************************************************/
    261 
    262 void
    263 AcpiEvTerminate (
    264     void)
    265 {
    266     UINT32                  i;
    267     ACPI_STATUS             Status;
    268 
    269 
    270     ACPI_FUNCTION_TRACE (EvTerminate);
    271 
    272 
    273     if (AcpiGbl_EventsInitialized)
    274     {
    275         /*
    276          * Disable all event-related functionality. In all cases, on error,
    277          * print a message but obviously we don't abort.
    278          */
    279 
    280         /* Disable all fixed events */
    281 
    282         for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++)
    283         {
    284             Status = AcpiDisableEvent (i, 0);
    285             if (ACPI_FAILURE (Status))
    286             {
    287                 ACPI_ERROR ((AE_INFO,
    288                     "Could not disable fixed event %u", (UINT32) i));
    289             }
    290         }
    291 
    292         /* Disable all GPEs in all GPE blocks */
    293 
    294         Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL);
    295 
    296         Status = AcpiEvRemoveGlobalLockHandler ();
    297         if (ACPI_FAILURE(Status))
    298         {
    299             ACPI_ERROR ((AE_INFO,
    300                 "Could not remove Global Lock handler"));
    301         }
    302 
    303         AcpiGbl_EventsInitialized = FALSE;
    304     }
    305 
    306     /* Remove SCI handlers */
    307 
    308     Status = AcpiEvRemoveAllSciHandlers ();
    309     if (ACPI_FAILURE(Status))
    310     {
    311         ACPI_ERROR ((AE_INFO,
    312             "Could not remove SCI handler"));
    313     }
    314 
    315     /* Deallocate all handler objects installed within GPE info structs */
    316 
    317     Status = AcpiEvWalkGpeList (AcpiEvDeleteGpeHandlers, NULL);
    318 
    319     /* Return to original mode if necessary */
    320 
    321     if (AcpiGbl_OriginalMode == ACPI_SYS_MODE_LEGACY)
    322     {
    323         Status = AcpiDisable ();
    324         if (ACPI_FAILURE (Status))
    325         {
    326             ACPI_WARNING ((AE_INFO, "AcpiDisable failed"));
    327         }
    328     }
    329     return_VOID;
    330 }
    331 
    332 #endif /* !ACPI_REDUCED_HARDWARE */
    333