ACPICA: Update header files copyrights to 2012
[deliverable/linux.git] / drivers / acpi / acpica / evxface.c
index 44bef5744ebb159f383f6b19515cf6346f656582..6a8b53789be46ca286b372c3ac5cf9e18ee398f1 100644 (file)
 ACPI_MODULE_NAME("evxface")
 
 
-/*******************************************************************************
- *
- * FUNCTION:    acpi_populate_handler_object
- *
- * PARAMETERS:  handler_obj        - Handler object to populate
- *              handler_type       - The type of handler:
- *                                  ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
- *                                  ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
- *                                  ACPI_ALL_NOTIFY:  both system and device
- *              handler            - Address of the handler
- *              context            - Value passed to the handler on each GPE
- *              next               - Address of a handler object to link to
- *
- * RETURN:      None
- *
- * DESCRIPTION: Populate a handler object.
- *
- ******************************************************************************/
-static void
-acpi_populate_handler_object(struct acpi_object_notify_handler *handler_obj,
-                            u32 handler_type,
-                            acpi_notify_handler handler, void *context,
-                            struct acpi_object_notify_handler *next)
-{
-       handler_obj->handler_type = handler_type;
-       handler_obj->handler = handler;
-       handler_obj->context = context;
-       handler_obj->next = next;
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_add_handler_object
- *
- * PARAMETERS:  parent_obj         - Parent of the new object
- *              handler            - Address of the handler
- *              context            - Value passed to the handler on each GPE
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Create a new handler object and populate it.
- *
- ******************************************************************************/
-static acpi_status
-acpi_add_handler_object(struct acpi_object_notify_handler *parent_obj,
-                       acpi_notify_handler handler, void *context)
-{
-       struct acpi_object_notify_handler *handler_obj;
-
-       /* The parent must not be a defice notify handler object. */
-       if (parent_obj->handler_type & ACPI_DEVICE_NOTIFY)
-               return AE_BAD_PARAMETER;
-
-       handler_obj = ACPI_ALLOCATE_ZEROED(sizeof(*handler_obj));
-       if (!handler_obj)
-               return AE_NO_MEMORY;
-
-       acpi_populate_handler_object(handler_obj,
-                                       ACPI_SYSTEM_NOTIFY,
-                                       handler, context,
-                                       parent_obj->next);
-       parent_obj->next = handler_obj;
-
-       return AE_OK;
-}
-
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_install_notify_handler
  *
  * PARAMETERS:  Device          - The device for which notifies will be handled
  *              handler_type    - The type of handler:
- *                                  ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
- *                                  ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
- *                                  ACPI_ALL_NOTIFY:  both system and device
+ *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
+ *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
+ *                                  ACPI_ALL_NOTIFY:    Both System and Device
  *              Handler         - Address of the handler
  *              Context         - Value passed to the handler on each GPE
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Install a handler for notifies on an ACPI device
+ * DESCRIPTION: Install a handler for notifications on an ACPI Device,
+ *              thermal_zone, or Processor object.
+ *
+ * NOTES:       The Root namespace object may have only one handler for each
+ *              type of notify (System/Device). Device/Thermal/Processor objects
+ *              may have one device notify handler, and multiple system notify
+ *              handlers.
  *
  ******************************************************************************/
 acpi_status
@@ -141,17 +80,19 @@ acpi_install_notify_handler(acpi_handle device,
                            u32 handler_type,
                            acpi_notify_handler handler, void *context)
 {
+       struct acpi_namespace_node *node =
+           ACPI_CAST_PTR(struct acpi_namespace_node, device);
        union acpi_operand_object *obj_desc;
-       union acpi_operand_object *notify_obj;
-       struct acpi_namespace_node *node;
+       union acpi_operand_object *handler_obj;
        acpi_status status;
+       u32 i;
 
        ACPI_FUNCTION_TRACE(acpi_install_notify_handler);
 
        /* Parameter validation */
 
-       if ((!device) ||
-           (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
+       if ((!device) || (!handler) || (!handler_type) ||
+           (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
                return_ACPI_STATUS(AE_BAD_PARAMETER);
        }
 
@@ -160,144 +101,112 @@ acpi_install_notify_handler(acpi_handle device,
                return_ACPI_STATUS(status);
        }
 
-       /* Convert and validate the device handle */
-
-       node = acpi_ns_validate_handle(device);
-       if (!node) {
-               status = AE_BAD_PARAMETER;
-               goto unlock_and_exit;
-       }
-
        /*
         * Root Object:
         * Registering a notify handler on the root object indicates that the
         * caller wishes to receive notifications for all objects. Note that
-        * only one <external> global handler can be regsitered (per notify type).
+        * only one global handler can be registered per notify type.
+        * Ensure that a handler is not already installed.
         */
        if (device == ACPI_ROOT_OBJECT) {
+               for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
+                       if (handler_type & (i + 1)) {
+                               if (acpi_gbl_global_notify[i].handler) {
+                                       status = AE_ALREADY_EXISTS;
+                                       goto unlock_and_exit;
+                               }
 
-               /* Make sure the handler is not already installed */
-
-               if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
-                    acpi_gbl_system_notify.handler) ||
-                   ((handler_type & ACPI_DEVICE_NOTIFY) &&
-                    acpi_gbl_device_notify.handler)) {
-                       status = AE_ALREADY_EXISTS;
-                       goto unlock_and_exit;
-               }
-
-               if (handler_type & ACPI_SYSTEM_NOTIFY) {
-                       acpi_gbl_system_notify.node = node;
-                       acpi_gbl_system_notify.handler = handler;
-                       acpi_gbl_system_notify.context = context;
-               }
-
-               if (handler_type & ACPI_DEVICE_NOTIFY) {
-                       acpi_gbl_device_notify.node = node;
-                       acpi_gbl_device_notify.handler = handler;
-                       acpi_gbl_device_notify.context = context;
+                               acpi_gbl_global_notify[i].handler = handler;
+                               acpi_gbl_global_notify[i].context = context;
+                       }
                }
 
-               /* Global notify handler installed */
+               goto unlock_and_exit;   /* Global notify handler installed, all done */
        }
 
        /*
         * All Other Objects:
-        * Caller will only receive notifications specific to the target object.
-        * Note that only certain object types can receive notifications.
+        * Caller will only receive notifications specific to the target
+        * object. Note that only certain object types are allowed to
+        * receive notifications.
         */
-       else {
-               /* Notifies allowed on this object? */
 
-               if (!acpi_ev_is_notify_object(node)) {
-                       status = AE_TYPE;
-                       goto unlock_and_exit;
-               }
+       /* Are Notifies allowed on this object? */
 
-               /* Check for an existing internal object */
+       if (!acpi_ev_is_notify_object(node)) {
+               status = AE_TYPE;
+               goto unlock_and_exit;
+       }
 
-               obj_desc = acpi_ns_get_attached_object(node);
-               if (obj_desc) {
+       /* Check for an existing internal object, might not exist */
 
-                       /* Object exists. */
+       obj_desc = acpi_ns_get_attached_object(node);
+       if (!obj_desc) {
 
-                       /* For a device notify, make sure there's no handler. */
-                       if ((handler_type & ACPI_DEVICE_NOTIFY) &&
-                            obj_desc->common_notify.device_notify) {
-                               status = AE_ALREADY_EXISTS;
-                               goto unlock_and_exit;
-                       }
+               /* Create a new object */
 
-                       /* System notifies may have more handlers installed. */
-                       notify_obj = obj_desc->common_notify.system_notify;
+               obj_desc = acpi_ut_create_internal_object(node->type);
+               if (!obj_desc) {
+                       status = AE_NO_MEMORY;
+                       goto unlock_and_exit;
+               }
 
-                       if ((handler_type & ACPI_SYSTEM_NOTIFY) && notify_obj) {
-                               struct acpi_object_notify_handler *parent_obj;
+               /* Attach new object to the Node, remove local reference */
 
-                               if (handler_type & ACPI_DEVICE_NOTIFY) {
+               status = acpi_ns_attach_object(device, obj_desc, node->type);
+               acpi_ut_remove_reference(obj_desc);
+               if (ACPI_FAILURE(status)) {
+                       goto unlock_and_exit;
+               }
+       }
+
+       /* Ensure that the handler is not already installed in the lists */
+
+       for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
+               if (handler_type & (i + 1)) {
+                       handler_obj = obj_desc->common_notify.notify_list[i];
+                       while (handler_obj) {
+                               if (handler_obj->notify.handler == handler) {
                                        status = AE_ALREADY_EXISTS;
                                        goto unlock_and_exit;
                                }
 
-                               parent_obj = &notify_obj->notify;
-                               status = acpi_add_handler_object(parent_obj,
-                                                                handler,
-                                                                context);
-                               goto unlock_and_exit;
-                       }
-               } else {
-                       /* Create a new object */
-
-                       obj_desc = acpi_ut_create_internal_object(node->type);
-                       if (!obj_desc) {
-                               status = AE_NO_MEMORY;
-                               goto unlock_and_exit;
-                       }
-
-                       /* Attach new object to the Node */
-
-                       status =
-                           acpi_ns_attach_object(device, obj_desc, node->type);
-
-                       /* Remove local reference to the object */
-
-                       acpi_ut_remove_reference(obj_desc);
-                       if (ACPI_FAILURE(status)) {
-                               goto unlock_and_exit;
+                               handler_obj = handler_obj->notify.next[i];
                        }
                }
+       }
 
-               /* Install the handler */
+       /* Create and populate a new notify handler object */
 
-               notify_obj =
-                   acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY);
-               if (!notify_obj) {
-                       status = AE_NO_MEMORY;
-                       goto unlock_and_exit;
-               }
+       handler_obj = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY);
+       if (!handler_obj) {
+               status = AE_NO_MEMORY;
+               goto unlock_and_exit;
+       }
 
-               acpi_populate_handler_object(&notify_obj->notify,
-                                               handler_type,
-                                               handler, context,
-                                               NULL);
+       handler_obj->notify.node = node;
+       handler_obj->notify.handler_type = handler_type;
+       handler_obj->notify.handler = handler;
+       handler_obj->notify.context = context;
 
-               if (handler_type & ACPI_SYSTEM_NOTIFY) {
-                       obj_desc->common_notify.system_notify = notify_obj;
-               }
+       /* Install the handler at the list head(s) */
 
-               if (handler_type & ACPI_DEVICE_NOTIFY) {
-                       obj_desc->common_notify.device_notify = notify_obj;
-               }
+       for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
+               if (handler_type & (i + 1)) {
+                       handler_obj->notify.next[i] =
+                           obj_desc->common_notify.notify_list[i];
 
-               if (handler_type == ACPI_ALL_NOTIFY) {
+                       obj_desc->common_notify.notify_list[i] = handler_obj;
+               }
+       }
 
-                       /* Extra ref if installed in both */
+       /* Add an extra reference if handler was installed in both lists */
 
-                       acpi_ut_add_reference(notify_obj);
-               }
+       if (handler_type == ACPI_ALL_NOTIFY) {
+               acpi_ut_add_reference(handler_obj);
        }
 
-      unlock_and_exit:
+unlock_and_exit:
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
        return_ACPI_STATUS(status);
 }
@@ -308,11 +217,11 @@ ACPI_EXPORT_SYMBOL(acpi_install_notify_handler)
  *
  * FUNCTION:    acpi_remove_notify_handler
  *
- * PARAMETERS:  Device          - The device for which notifies will be handled
+ * PARAMETERS:  Device          - The device for which the handler is installed
  *              handler_type    - The type of handler:
- *                                  ACPI_SYSTEM_NOTIFY: system_handler (00-7f)
- *                                  ACPI_DEVICE_NOTIFY: driver_handler (80-ff)
- *                                  ACPI_ALL_NOTIFY:  both system and device
+ *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
+ *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
+ *                                  ACPI_ALL_NOTIFY:    Both System and Device
  *              Handler         - Address of the handler
  *
  * RETURN:      Status
@@ -324,165 +233,106 @@ acpi_status
 acpi_remove_notify_handler(acpi_handle device,
                           u32 handler_type, acpi_notify_handler handler)
 {
-       union acpi_operand_object *notify_obj;
+       struct acpi_namespace_node *node =
+           ACPI_CAST_PTR(struct acpi_namespace_node, device);
        union acpi_operand_object *obj_desc;
-       struct acpi_namespace_node *node;
+       union acpi_operand_object *handler_obj;
+       union acpi_operand_object *previous_handler_obj;
        acpi_status status;
+       u32 i;
 
        ACPI_FUNCTION_TRACE(acpi_remove_notify_handler);
 
        /* Parameter validation */
 
-       if ((!device) ||
-           (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
-               status = AE_BAD_PARAMETER;
-               goto exit;
+       if ((!device) || (!handler) || (!handler_type) ||
+           (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
+               return_ACPI_STATUS(AE_BAD_PARAMETER);
        }
-
-
        /* Make sure all deferred tasks are completed */
-       acpi_os_wait_events_complete(NULL);
+
+       acpi_os_wait_events_complete();
 
        status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
        if (ACPI_FAILURE(status)) {
-               goto exit;
-       }
-
-       /* Convert and validate the device handle */
-
-       node = acpi_ns_validate_handle(device);
-       if (!node) {
-               status = AE_BAD_PARAMETER;
-               goto unlock_and_exit;
+               return_ACPI_STATUS(status);
        }
 
-       /* Root Object */
+       /* Root Object. Global handlers are removed here */
 
        if (device == ACPI_ROOT_OBJECT) {
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                 "Removing notify handler for namespace root object\n"));
+               for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
+                       if (handler_type & (i + 1)) {
+                               if (!acpi_gbl_global_notify[i].handler ||
+                                   (acpi_gbl_global_notify[i].handler !=
+                                    handler)) {
+                                       status = AE_NOT_EXIST;
+                                       goto unlock_and_exit;
+                               }
 
-               if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
-                    !acpi_gbl_system_notify.handler) ||
-                   ((handler_type & ACPI_DEVICE_NOTIFY) &&
-                    !acpi_gbl_device_notify.handler)) {
-                       status = AE_NOT_EXIST;
-                       goto unlock_and_exit;
-               }
+                               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                                 "Removing global notify handler\n"));
 
-               if (handler_type & ACPI_SYSTEM_NOTIFY) {
-                       acpi_gbl_system_notify.node = NULL;
-                       acpi_gbl_system_notify.handler = NULL;
-                       acpi_gbl_system_notify.context = NULL;
+                               acpi_gbl_global_notify[i].handler = NULL;
+                               acpi_gbl_global_notify[i].context = NULL;
+                       }
                }
 
-               if (handler_type & ACPI_DEVICE_NOTIFY) {
-                       acpi_gbl_device_notify.node = NULL;
-                       acpi_gbl_device_notify.handler = NULL;
-                       acpi_gbl_device_notify.context = NULL;
-               }
+               goto unlock_and_exit;
        }
 
-       /* All Other Objects */
-
-       else {
-               /* Notifies allowed on this object? */
+       /* All other objects: Are Notifies allowed on this object? */
 
-               if (!acpi_ev_is_notify_object(node)) {
-                       status = AE_TYPE;
-                       goto unlock_and_exit;
-               }
+       if (!acpi_ev_is_notify_object(node)) {
+               status = AE_TYPE;
+               goto unlock_and_exit;
+       }
 
-               /* Check for an existing internal object */
+       /* Must have an existing internal object */
 
-               obj_desc = acpi_ns_get_attached_object(node);
-               if (!obj_desc) {
-                       status = AE_NOT_EXIST;
-                       goto unlock_and_exit;
-               }
+       obj_desc = acpi_ns_get_attached_object(node);
+       if (!obj_desc) {
+               status = AE_NOT_EXIST;
+               goto unlock_and_exit;
+       }
 
-               /* Object exists - make sure there's an existing handler */
+       /* Internal object exists. Find the handler and remove it */
 
-               if (handler_type & ACPI_SYSTEM_NOTIFY) {
-                       struct acpi_object_notify_handler *handler_obj;
-                       struct acpi_object_notify_handler *parent_obj;
+       for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
+               if (handler_type & (i + 1)) {
+                       handler_obj = obj_desc->common_notify.notify_list[i];
+                       previous_handler_obj = NULL;
 
-                       notify_obj = obj_desc->common_notify.system_notify;
-                       if (!notify_obj) {
-                               status = AE_NOT_EXIST;
-                               goto unlock_and_exit;
-                       }
+                       /* Attempt to find the handler in the handler list */
 
-                       handler_obj = &notify_obj->notify;
-                       parent_obj = NULL;
-                       while (handler_obj->handler != handler) {
-                               if (handler_obj->next) {
-                                       parent_obj = handler_obj;
-                                       handler_obj = handler_obj->next;
-                               } else {
-                                       break;
-                               }
+                       while (handler_obj &&
+                              (handler_obj->notify.handler != handler)) {
+                               previous_handler_obj = handler_obj;
+                               handler_obj = handler_obj->notify.next[i];
                        }
 
-                       if (handler_obj->handler != handler) {
-                               status = AE_BAD_PARAMETER;
+                       if (!handler_obj) {
+                               status = AE_NOT_EXIST;
                                goto unlock_and_exit;
                        }
 
-                       /*
-                        * Remove the handler.  There are three possible cases.
-                        * First, we may need to remove a non-embedded object.
-                        * Second, we may need to remove the embedded object's
-                        * handler data, while non-embedded objects exist.
-                        * Finally, we may need to remove the embedded object
-                        * entirely along with its container.
-                        */
-                       if (parent_obj) {
-                               /* Non-embedded object is being removed. */
-                               parent_obj->next = handler_obj->next;
-                               ACPI_FREE(handler_obj);
-                       } else if (notify_obj->notify.next) {
-                               /*
-                                * The handler matches the embedded object, but
-                                * there are more handler objects in the list.
-                                * Replace the embedded object's data with the
-                                * first next object's data and remove that
-                                * object.
-                                */
-                               parent_obj = &notify_obj->notify;
-                               handler_obj = notify_obj->notify.next;
-                               *parent_obj = *handler_obj;
-                               ACPI_FREE(handler_obj);
-                       } else {
-                               /* No more handler objects in the list. */
-                               obj_desc->common_notify.system_notify = NULL;
-                               acpi_ut_remove_reference(notify_obj);
-                       }
-               }
+                       /* Remove the handler object from the list */
 
-               if (handler_type & ACPI_DEVICE_NOTIFY) {
-                       notify_obj = obj_desc->common_notify.device_notify;
-                       if (!notify_obj) {
-                               status = AE_NOT_EXIST;
-                               goto unlock_and_exit;
-                       }
+                       if (previous_handler_obj) {     /* Handler is not at the list head */
+                               previous_handler_obj->notify.next[i] =
+                                   handler_obj->notify.next[i];
+                       } else {        /* Handler is at the list head */
 
-                       if (notify_obj->notify.handler != handler) {
-                               status = AE_BAD_PARAMETER;
-                               goto unlock_and_exit;
+                               obj_desc->common_notify.notify_list[i] =
+                                   handler_obj->notify.next[i];
                        }
 
-                       /* Remove the handler */
-                       obj_desc->common_notify.device_notify = NULL;
-                       acpi_ut_remove_reference(notify_obj);
+                       acpi_ut_remove_reference(handler_obj);
                }
        }
 
-      unlock_and_exit:
+unlock_and_exit:
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-      exit:
-       if (ACPI_FAILURE(status))
-               ACPI_EXCEPTION((AE_INFO, status, "Removing notify handler"));
        return_ACPI_STATUS(status);
 }
 
@@ -849,7 +699,7 @@ acpi_remove_gpe_handler(acpi_handle gpe_device,
 
        /* Make sure all deferred tasks are completed */
 
-       acpi_os_wait_events_complete(NULL);
+       acpi_os_wait_events_complete();
 
        status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
        if (ACPI_FAILURE(status)) {
This page took 0.142595 seconds and 5 git commands to generate.