Print this page
update to acpica-unix2-20140114
update to acpica-unix2-20130927
acpica-unix2-20130823
PANKOVs restructure

@@ -3,11 +3,11 @@
  * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
  *
  *****************************************************************************/
 
 /*
- * Copyright (C) 2000 - 2011, Intel Corp.
+ * Copyright (C) 2000 - 2014, Intel Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:

@@ -41,10 +41,11 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
 
 #define __EVXFGPE_C__
+#define EXPORT_ACPI_INTERFACES
 
 #include "acpi.h"
 #include "accommon.h"
 #include "acevents.h"
 #include "acnamesp.h"

@@ -51,10 +52,11 @@
 
 #define _COMPONENT          ACPI_EVENTS
         ACPI_MODULE_NAME    ("evxfgpe")
 
 
+#if (!ACPI_REDUCED_HARDWARE) /* Entire module */
 /*******************************************************************************
  *
  * FUNCTION:    AcpiUpdateAllGpes
  *
  * PARAMETERS:  None

@@ -80,11 +82,11 @@
     void)
 {
     ACPI_STATUS             Status;
 
 
-    ACPI_FUNCTION_TRACE (AcpiUpdateGpes);
+    ACPI_FUNCTION_TRACE (AcpiUpdateAllGpes);
 
 
     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
     if (ACPI_FAILURE (Status))
     {

@@ -247,18 +249,21 @@
     /* 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:

@@ -292,13 +297,15 @@
 AcpiSetupGpeForWake (
     ACPI_HANDLE             WakeDevice,
     ACPI_HANDLE             GpeDevice,
     UINT32                  GpeNumber)
 {
-    ACPI_STATUS             Status = AE_BAD_PARAMETER;
+    ACPI_STATUS             Status;
     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
     ACPI_NAMESPACE_NODE     *DeviceNode;
+    ACPI_GPE_NOTIFY_INFO    *Notify;
+    ACPI_GPE_NOTIFY_INFO    *NewNotify;
     ACPI_CPU_FLAGS          Flags;
 
 
     ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake);
 

@@ -330,36 +337,92 @@
     if (DeviceNode->Type != ACPI_TYPE_DEVICE)
     {
         return_ACPI_STATUS (AE_BAD_PARAMETER);
     }
 
+    /*
+     * Allocate a new notify object up front, in case it is needed.
+     * Memory allocation while holding a spinlock is a big no-no
+     * on some hosts.
+     */
+    NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO));
+    if (!NewNotify)
+    {
+        return_ACPI_STATUS (AE_NO_MEMORY);
+    }
+
     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
 
     /* Ensure that we have a valid GPE number */
 
     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
-    if (GpeEventInfo)
+    if (!GpeEventInfo)
     {
+        Status = AE_BAD_PARAMETER;
+        goto UnlockAndExit;
+    }
+
         /*
          * 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
+     * WakeDevice will be notified whenever this GPE fires. This is
+     * known as an "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)
         {
+        /*
+         * This is the first device for implicit notify on this GPE.
+         * Just set the flags here, and enter the NOTIFY block below.
+         */
             GpeEventInfo->Flags =
                 (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
-            GpeEventInfo->Dispatch.DeviceNode = DeviceNode;
         }
 
+    /*
+     * If we already have an implicit notify on this GPE, add
+     * this device to the notify list.
+     */
+    if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
+            ACPI_GPE_DISPATCH_NOTIFY)
+    {
+        /* Ensure that the device is not already in the list */
+
+        Notify = GpeEventInfo->Dispatch.NotifyList;
+        while (Notify)
+        {
+            if (Notify->DeviceNode == DeviceNode)
+            {
+                Status = AE_ALREADY_EXISTS;
+                goto UnlockAndExit;
+            }
+            Notify = Notify->Next;
+        }
+
+        /* Add this device to the notify list for this GPE */
+
+        NewNotify->DeviceNode = DeviceNode;
+        NewNotify->Next = GpeEventInfo->Dispatch.NotifyList;
+        GpeEventInfo->Dispatch.NotifyList = NewNotify;
+        NewNotify = NULL;
+    }
+
+    /* Mark the GPE as a possible wake event */
+
         GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
         Status = AE_OK;
-    }
 
+
+UnlockAndExit:
     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
+
+    /* Delete the notify object if it was not used above */
+
+    if (NewNotify)
+    {
+        ACPI_FREE (NewNotify);
+    }
     return_ACPI_STATUS (Status);
 }
 
 ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake)
 

@@ -419,25 +482,28 @@
     {
         Status = AE_NOT_EXIST;
         goto UnlockAndExit;
     }
 
-    RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo);
+    RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
 
     /* 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;
     }
 

@@ -713,20 +779,34 @@
     }
 
     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
     if (ACPI_FAILURE (Status))
     {
-        return (Status);
+        return_ACPI_STATUS (Status);
     }
 
     Node = AcpiNsValidateHandle (GpeDevice);
     if (!Node)
     {
         Status = AE_BAD_PARAMETER;
         goto UnlockAndExit;
     }
 
+    /* Validate the parent device */
+
+    if (Node->Type != ACPI_TYPE_DEVICE)
+    {
+        Status = AE_TYPE;
+        goto UnlockAndExit;
+    }
+
+    if (Node->Object)
+    {
+        Status = AE_ALREADY_EXISTS;
+        goto UnlockAndExit;
+    }
+
     /*
      * For user-installed GPE Block Devices, the GpeBlockBaseNumber
      * is always zero
      */
     Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress, RegisterCount,

@@ -806,20 +886,28 @@
     }
 
     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
     if (ACPI_FAILURE (Status))
     {
-        return (Status);
+        return_ACPI_STATUS (Status);
     }
 
     Node = AcpiNsValidateHandle (GpeDevice);
     if (!Node)
     {
         Status = AE_BAD_PARAMETER;
         goto UnlockAndExit;
     }
 
+    /* Validate the parent device */
+
+    if (Node->Type != ACPI_TYPE_DEVICE)
+    {
+        Status = AE_TYPE;
+        goto UnlockAndExit;
+    }
+
     /* Get the DeviceObject attached to the node */
 
     ObjDesc = AcpiNsGetAttachedObject (Node);
     if (!ObjDesc ||
         !ObjDesc->Device.GpeBlock)

@@ -896,5 +984,7 @@
     *GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);
     return_ACPI_STATUS (Info.Status);
 }
 
 ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)
+
+#endif /* !ACPI_REDUCED_HARDWARE */