Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 318793
b: refs/heads/master
c: 5816b34
h: refs/heads/master
i:
  318791: 3535df2
v: v3
  • Loading branch information
Bob Moore authored and Len Brown committed Jul 14, 2012
1 parent 460896b commit 2098b37
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 51 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: e40d5940396aa4002feeab8323224b5c7f84246c
refs/heads/master: 5816b3430c4b5f31d9c35af1da7be721c9518137
11 changes: 9 additions & 2 deletions trunk/drivers/acpi/acpica/aclocal.h
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,13 @@ struct acpi_gpe_handler_info {
u8 originally_enabled; /* True if GPE was originally enabled */
};

/* Notify info for implicit notify, multiple device objects */

struct acpi_gpe_notify_info {
struct acpi_namespace_node *device_node; /* Device to be notified */
struct acpi_gpe_notify_info *next;
};

struct acpi_gpe_notify_object {
struct acpi_namespace_node *node;
struct acpi_gpe_notify_object *next;
Expand All @@ -412,15 +419,15 @@ struct acpi_gpe_notify_object {
union acpi_gpe_dispatch_info {
struct acpi_namespace_node *method_node; /* Method node for this GPE level */
struct acpi_gpe_handler_info *handler; /* Installed GPE handler */
struct acpi_gpe_notify_object device; /* List of _PRW devices for implicit notify */
struct acpi_gpe_notify_info *notify_list; /* List of _PRW devices for implicit notifies */
};

/*
* Information about a GPE, one per each GPE in an array.
* NOTE: Important to keep this struct as small as possible.
*/
struct acpi_gpe_event_info {
union acpi_gpe_dispatch_info dispatch; /* Either Method or Handler */
union acpi_gpe_dispatch_info dispatch; /* Either Method, Handler, or notify_list */
struct acpi_gpe_register_info *register_info; /* Backpointer to register info */
u8 flags; /* Misc info about this GPE */
u8 gpe_number; /* This GPE */
Expand Down
22 changes: 11 additions & 11 deletions trunk/drivers/acpi/acpica/evgpe.c
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
acpi_status status;
struct acpi_gpe_event_info *local_gpe_event_info;
struct acpi_evaluate_info *info;
struct acpi_gpe_notify_object *notify_object;
struct acpi_gpe_notify_info *notify;

ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method);

Expand Down Expand Up @@ -517,17 +517,17 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
* completes. The notify handlers are NOT invoked synchronously
* from this thread -- because handlers may in turn run other
* control methods.
*
* June 2012: Expand implicit notify mechanism to support
* notifies on multiple device objects.
*/
status = acpi_ev_queue_notify_request(
local_gpe_event_info->dispatch.device.node,
ACPI_NOTIFY_DEVICE_WAKE);

notify_object = local_gpe_event_info->dispatch.device.next;
while (ACPI_SUCCESS(status) && notify_object) {
status = acpi_ev_queue_notify_request(
notify_object->node,
ACPI_NOTIFY_DEVICE_WAKE);
notify_object = notify_object->next;
notify = local_gpe_event_info->dispatch.notify_list;
while (ACPI_SUCCESS(status) && notify) {
status =
acpi_ev_queue_notify_request(notify->device_node,
ACPI_NOTIFY_DEVICE_WAKE);

notify = notify->next;
}

break;
Expand Down
20 changes: 20 additions & 0 deletions trunk/drivers/acpi/acpica/evgpeutil.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,8 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
void *context)
{
struct acpi_gpe_event_info *gpe_event_info;
struct acpi_gpe_notify_info *notify;
struct acpi_gpe_notify_info *next;
u32 i;
u32 j;

Expand All @@ -365,10 +367,28 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,

if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
ACPI_GPE_DISPATCH_HANDLER) {

/* Delete an installed handler block */

ACPI_FREE(gpe_event_info->dispatch.handler);
gpe_event_info->dispatch.handler = NULL;
gpe_event_info->flags &=
~ACPI_GPE_DISPATCH_MASK;
} else if ((gpe_event_info->
flags & ACPI_GPE_DISPATCH_MASK) ==
ACPI_GPE_DISPATCH_NOTIFY) {

/* Delete the implicit notification device list */

notify = gpe_event_info->dispatch.notify_list;
while (notify) {
next = notify->next;
ACPI_FREE(notify);
notify = next;
}
gpe_event_info->dispatch.notify_list = NULL;
gpe_event_info->flags &=
~ACPI_GPE_DISPATCH_MASK;
}
}
}
Expand Down
106 changes: 69 additions & 37 deletions trunk/drivers/acpi/acpica/evxfgpe.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,12 +197,12 @@ acpi_status
acpi_setup_gpe_for_wake(acpi_handle wake_device,
acpi_handle gpe_device, u32 gpe_number)
{
acpi_status status = AE_BAD_PARAMETER;
acpi_status status;
struct acpi_gpe_event_info *gpe_event_info;
struct acpi_namespace_node *device_node;
struct acpi_gpe_notify_object *notify_object;
struct acpi_gpe_notify_info *notify;
struct acpi_gpe_notify_info *new_notify;
acpi_cpu_flags flags;
u8 gpe_dispatch_mask;

ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake);

Expand All @@ -216,63 +216,95 @@ acpi_setup_gpe_for_wake(acpi_handle wake_device,
return_ACPI_STATUS(AE_BAD_PARAMETER);
}

/* Handle root object case */

if (wake_device == ACPI_ROOT_OBJECT) {
device_node = acpi_gbl_root_node;
} else {
device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
}

/* Validate WakeDevice is of type Device */

if (device_node->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.
*/
new_notify = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_notify_info));
if (!new_notify) {
return_ACPI_STATUS(AE_NO_MEMORY);
}

flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);

/* Ensure that we have a valid GPE number */

gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
if (!gpe_event_info) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}

if (wake_device == ACPI_ROOT_OBJECT) {
goto out;
}

/*
* If there is no method or handler for this GPE, then the
* wake_device will be notified whenever this GPE fires (aka
* "implicit notify") Note: The GPE is assumed to be
* wake_device 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).
*/
gpe_dispatch_mask = gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK;
if (gpe_dispatch_mask != ACPI_GPE_DISPATCH_NONE
&& gpe_dispatch_mask != ACPI_GPE_DISPATCH_NOTIFY) {
goto out;
}

/* Validate wake_device is of type Device */

device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
if (device_node->type != ACPI_TYPE_DEVICE) {
goto unlock_and_exit;
if ((gpe_event_info->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.
*/
gpe_event_info->flags =
(ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
}

if (gpe_dispatch_mask == ACPI_GPE_DISPATCH_NONE) {
gpe_event_info->flags = (ACPI_GPE_DISPATCH_NOTIFY |
ACPI_GPE_LEVEL_TRIGGERED);
gpe_event_info->dispatch.device.node = device_node;
gpe_event_info->dispatch.device.next = NULL;
} else {
/* There are multiple devices to notify implicitly. */

notify_object = ACPI_ALLOCATE_ZEROED(sizeof(*notify_object));
if (!notify_object) {
status = AE_NO_MEMORY;
goto unlock_and_exit;
/*
* If we already have an implicit notify on this GPE, add
* this device to the notify list.
*/
if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
ACPI_GPE_DISPATCH_NOTIFY) {

/* Ensure that the device is not already in the list */

notify = gpe_event_info->dispatch.notify_list;
while (notify) {
if (notify->device_node == device_node) {
status = AE_ALREADY_EXISTS;
goto unlock_and_exit;
}
notify = notify->next;
}

notify_object->node = device_node;
notify_object->next = gpe_event_info->dispatch.device.next;
gpe_event_info->dispatch.device.next = notify_object;
/* Add this device to the notify list for this GPE */

new_notify->device_node = device_node;
new_notify->next = gpe_event_info->dispatch.notify_list;
gpe_event_info->dispatch.notify_list = new_notify;
new_notify = NULL;
}

out:
/* Mark the GPE as a possible wake event */

gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
status = AE_OK;

unlock_and_exit:
unlock_and_exit:
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);

/* Delete the notify object if it was not used above */

if (new_notify) {
ACPI_FREE(new_notify);
}
return_ACPI_STATUS(status);
}
ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake)
Expand Down

0 comments on commit 2098b37

Please sign in to comment.