ACPICA: Implicit notify support
This feature provides an automatic device notification for wake devices
when a wakeup GPE occurs and there is no corresponding GPE method or
handler. Rather than ignoring such a GPE, an implicit AML Notify
operation is performed on the parent device object.
This feature is not part of the ACPI specification and is provided for
Windows compatibility only.
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c
index 99f77ab..fcf4a5c 100644
--- a/drivers/acpi/acpica/evxfgpe.c
+++ b/drivers/acpi/acpica/evxfgpe.c
@@ -166,39 +166,75 @@
}
ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
+
/*******************************************************************************
*
* FUNCTION: acpi_setup_gpe_for_wake
*
- * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
- * gpe_number - GPE level within the GPE block
+ * PARAMETERS: wake_device - Device associated with the GPE (via _PRW)
+ * gpe_device - Parent GPE Device. NULL for GPE0/GPE1
+ * gpe_number - GPE level within the GPE block
*
* RETURN: Status
*
- * DESCRIPTION: Set the ACPI_GPE_CAN_WAKE flag for the given GPE. If the GPE
- * has a corresponding method and is currently enabled, disable it
- * (GPEs with corresponding methods are enabled unconditionally
- * during initialization, but GPEs that can wake up are expected
- * to be initially disabled).
+ * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
+ * interface is intended to be used as the host executes the
+ * _PRW methods (Power Resources for Wake) in the system tables.
+ * Each _PRW appears under a Device Object (The wake_device), and
+ * contains the info for the wake GPE associated with the
+ * wake_device.
*
******************************************************************************/
-acpi_status acpi_setup_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number)
+acpi_status
+acpi_setup_gpe_for_wake(acpi_handle wake_device,
+ acpi_handle gpe_device, u32 gpe_number)
{
- acpi_status status = AE_OK;
+ acpi_status status = AE_BAD_PARAMETER;
struct acpi_gpe_event_info *gpe_event_info;
+ struct acpi_namespace_node *device_node;
acpi_cpu_flags flags;
ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake);
+ /* Parameter Validation */
+
+ if (!wake_device) {
+ /*
+ * By forcing wake_device to be valid, we automatically enable the
+ * implicit notify feature on all hosts.
+ */
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
+
+ /* 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) {
+ return_ACPI_STATUS(AE_BAD_PARAMETER);
+ }
+
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) {
+ /*
+ * 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
+ * level-triggered (for windows compatibility).
+ */
+ if ((gpe_event_info->flags & ACPI_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->flags |= ACPI_GPE_CAN_WAKE;
- } else {
- status = AE_BAD_PARAMETER;
+ status = AE_OK;
}
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);