Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 180989
b: refs/heads/master
c: 3f0be67
h: refs/heads/master
i:
  180987: 680f6eb
v: v3
  • Loading branch information
Rafael J. Wysocki authored and Jesse Barnes committed Feb 23, 2010
1 parent 73e2abc commit 3e7a995
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 40 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: f517709d65beed95f52f021b43e3035b52ef791a
refs/heads/master: 3f0be67188c60ebf1b5d00354b44b4b24f5af313
2 changes: 2 additions & 0 deletions trunk/drivers/acpi/acpica/acobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,10 @@ struct acpi_object_buffer_field {

struct acpi_object_notify_handler {
ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *node; /* Parent device */
u32 handler_type;
acpi_notify_handler handler;
void *context;
struct acpi_object_notify_handler *next;
};

struct acpi_object_addr_handler {
Expand Down
12 changes: 9 additions & 3 deletions trunk/drivers/acpi/acpica/evmisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,9 +259,15 @@ static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context)

handler_obj = notify_info->notify.handler_obj;
if (handler_obj) {
handler_obj->notify.handler(notify_info->notify.node,
notify_info->notify.value,
handler_obj->notify.context);
struct acpi_object_notify_handler *notifier;

notifier = &handler_obj->notify;
while (notifier) {
notifier->handler(notify_info->notify.node,
notify_info->notify.value,
notifier->context);
notifier = notifier->next;
}
}

/* All done with the info object */
Expand Down
175 changes: 139 additions & 36 deletions trunk/drivers/acpi/acpica/evxface.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,72 @@ acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)

ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler)

/*******************************************************************************
*
* 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
Expand Down Expand Up @@ -316,15 +382,32 @@ acpi_install_notify_handler(acpi_handle device,
obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {

/* Object exists - make sure there's no handler */
/* Object exists. */

if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
obj_desc->common_notify.system_notify) ||
((handler_type & ACPI_DEVICE_NOTIFY) &&
obj_desc->common_notify.device_notify)) {
/* 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;
}

/* System notifies may have more handlers installed. */
notify_obj = obj_desc->common_notify.system_notify;

if ((handler_type & ACPI_SYSTEM_NOTIFY) && notify_obj) {
struct acpi_object_notify_handler *parent_obj;

if (handler_type & ACPI_DEVICE_NOTIFY) {
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 */

Expand Down Expand Up @@ -356,9 +439,10 @@ acpi_install_notify_handler(acpi_handle device,
goto unlock_and_exit;
}

notify_obj->notify.node = node;
notify_obj->notify.handler = handler;
notify_obj->notify.context = context;
acpi_populate_handler_object(&notify_obj->notify,
handler_type,
handler, context,
NULL);

if (handler_type & ACPI_SYSTEM_NOTIFY) {
obj_desc->common_notify.system_notify = notify_obj;
Expand Down Expand Up @@ -418,6 +502,10 @@ acpi_remove_notify_handler(acpi_handle device,
goto exit;
}


/* Make sure all deferred tasks are completed */
acpi_os_wait_events_complete(NULL);

status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
goto exit;
Expand Down Expand Up @@ -445,15 +533,6 @@ acpi_remove_notify_handler(acpi_handle device,
goto unlock_and_exit;
}

/* Make sure all deferred tasks are completed */

(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
acpi_os_wait_events_complete(NULL);
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
goto exit;
}

if (handler_type & ACPI_SYSTEM_NOTIFY) {
acpi_gbl_system_notify.node = NULL;
acpi_gbl_system_notify.handler = NULL;
Expand Down Expand Up @@ -488,28 +567,60 @@ acpi_remove_notify_handler(acpi_handle device,
/* Object exists - make sure there's an existing handler */

if (handler_type & ACPI_SYSTEM_NOTIFY) {
struct acpi_object_notify_handler *handler_obj;
struct acpi_object_notify_handler *parent_obj;

notify_obj = obj_desc->common_notify.system_notify;
if (!notify_obj) {
status = AE_NOT_EXIST;
goto unlock_and_exit;
}

if (notify_obj->notify.handler != handler) {
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;
}
}

if (handler_obj->handler != handler) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
/* Make sure all deferred tasks are completed */

(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
acpi_os_wait_events_complete(NULL);
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
goto 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 */
obj_desc->common_notify.system_notify = NULL;
acpi_ut_remove_reference(notify_obj);
}

if (handler_type & ACPI_DEVICE_NOTIFY) {
Expand All @@ -523,14 +634,6 @@ acpi_remove_notify_handler(acpi_handle device,
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
/* Make sure all deferred tasks are completed */

(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
acpi_os_wait_events_complete(NULL);
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
goto exit;
}

/* Remove the handler */
obj_desc->common_notify.device_notify = NULL;
Expand Down

0 comments on commit 3e7a995

Please sign in to comment.