summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/evxfevnt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/acpica/evxfevnt.c')
-rw-r--r--drivers/acpi/acpica/evxfevnt.c249
1 files changed, 104 insertions, 145 deletions
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index 18b3f1468b7..0ec900da579 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -213,101 +213,71 @@ ACPI_EXPORT_SYMBOL(acpi_enable_event)
/*******************************************************************************
*
- * FUNCTION: acpi_clear_and_enable_gpe
- *
- * PARAMETERS: gpe_event_info - GPE to enable
- *
- * RETURN: Status
- *
- * DESCRIPTION: Clear the given GPE from stale events and enable it.
- *
- ******************************************************************************/
-static acpi_status
-acpi_clear_and_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
-{
- acpi_status status;
-
- /*
- * We will only allow a GPE to be enabled if it has either an
- * associated method (_Lxx/_Exx) or a handler. Otherwise, the
- * GPE will be immediately disabled by acpi_ev_gpe_dispatch the
- * first time it fires.
- */
- if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) {
- return_ACPI_STATUS(AE_NO_HANDLER);
- }
-
- /* Clear the GPE (of stale events) */
- status = acpi_hw_clear_gpe(gpe_event_info);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
-
- /* Enable the requested GPE */
- status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);
-
- return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_set_gpe
+ * FUNCTION: acpi_gpe_wakeup
*
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
* gpe_number - GPE level within the GPE block
- * action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
+ * Action - Enable or Disable
*
* RETURN: Status
*
- * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
- * the reference count mechanism used in the acpi_enable_gpe and
- * acpi_disable_gpe interfaces -- and should be used with care.
- *
- * Note: Typically used to disable a runtime GPE for short period of time,
- * then re-enable it, without disturbing the existing reference counts. This
- * is useful, for example, in the Embedded Controller (EC) driver.
+ * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit.
*
******************************************************************************/
-acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
+acpi_status acpi_gpe_wakeup(acpi_handle gpe_device, u32 gpe_number, u8 action)
{
+ acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
- acpi_status status;
+ struct acpi_gpe_register_info *gpe_register_info;
acpi_cpu_flags flags;
+ u32 register_bit;
- ACPI_FUNCTION_TRACE(acpi_set_gpe);
+ ACPI_FUNCTION_TRACE(acpi_gpe_wakeup);
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 (!gpe_event_info || !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
status = AE_BAD_PARAMETER;
goto unlock_and_exit;
}
+ gpe_register_info = gpe_event_info->register_info;
+ if (!gpe_register_info) {
+ status = AE_NOT_EXIST;
+ goto unlock_and_exit;
+ }
+
+ register_bit =
+ acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info);
+
/* Perform the action */
switch (action) {
case ACPI_GPE_ENABLE:
- status = acpi_clear_and_enable_gpe(gpe_event_info);
+ ACPI_SET_BIT(gpe_register_info->enable_for_wake,
+ (u8)register_bit);
break;
case ACPI_GPE_DISABLE:
- status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
+ ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
+ (u8)register_bit);
break;
default:
+ ACPI_ERROR((AE_INFO, "%u, Invalid action", action));
status = AE_BAD_PARAMETER;
break;
}
- unlock_and_exit:
+unlock_and_exit:
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
return_ACPI_STATUS(status);
}
-ACPI_EXPORT_SYMBOL(acpi_set_gpe)
+ACPI_EXPORT_SYMBOL(acpi_gpe_wakeup)
/*******************************************************************************
*
@@ -315,17 +285,14 @@ ACPI_EXPORT_SYMBOL(acpi_set_gpe)
*
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
* gpe_number - GPE level within the GPE block
- * gpe_type - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE
- * or both
*
* RETURN: Status
*
* DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
- * hardware-enabled (for runtime GPEs), or the GPE register mask
- * is updated (for wake GPEs).
+ * hardware-enabled.
*
******************************************************************************/
-acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
+acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
{
acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
@@ -333,12 +300,6 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
ACPI_FUNCTION_TRACE(acpi_enable_gpe);
- /* Parameter validation */
-
- if (!gpe_type || (gpe_type & ~ACPI_GPE_TYPE_WAKE_RUN)) {
- return_ACPI_STATUS(AE_BAD_PARAMETER);
- }
-
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
/* Ensure that we have a valid GPE number */
@@ -349,46 +310,19 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
goto unlock_and_exit;
}
- if (gpe_type & ACPI_GPE_TYPE_RUNTIME) {
- if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) {
- status = AE_LIMIT; /* Too many references */
- goto unlock_and_exit;
- }
-
- gpe_event_info->runtime_count++;
- if (gpe_event_info->runtime_count == 1) {
- status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
- if (ACPI_SUCCESS(status)) {
- status = acpi_clear_and_enable_gpe(gpe_event_info);
- }
-
- if (ACPI_FAILURE(status)) {
- gpe_event_info->runtime_count--;
- goto unlock_and_exit;
- }
- }
+ if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) {
+ status = AE_LIMIT; /* Too many references */
+ goto unlock_and_exit;
}
- if (gpe_type & ACPI_GPE_TYPE_WAKE) {
- /* The GPE must have the ability to wake the system */
-
- if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
- status = AE_TYPE;
- goto unlock_and_exit;
+ gpe_event_info->runtime_count++;
+ if (gpe_event_info->runtime_count == 1) {
+ status = acpi_ev_update_gpe_enable_mask(gpe_event_info);
+ if (ACPI_SUCCESS(status)) {
+ status = acpi_ev_enable_gpe(gpe_event_info);
}
-
- if (gpe_event_info->wakeup_count == ACPI_UINT8_MAX) {
- status = AE_LIMIT; /* Too many references */
- goto unlock_and_exit;
- }
-
- /*
- * Update the enable mask on the first wakeup reference. Wake GPEs
- * are only hardware-enabled just before sleeping.
- */
- gpe_event_info->wakeup_count++;
- if (gpe_event_info->wakeup_count == 1) {
- status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
+ if (ACPI_FAILURE(status)) {
+ gpe_event_info->runtime_count--;
}
}
@@ -404,8 +338,6 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
*
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
* gpe_number - GPE level within the GPE block
- * gpe_type - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE
- * or both
*
* RETURN: Status
*
@@ -414,7 +346,7 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
* the GPE mask bit disabled (for wake GPEs)
*
******************************************************************************/
-acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
+acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
{
acpi_status status = AE_OK;
struct acpi_gpe_event_info *gpe_event_info;
@@ -422,12 +354,6 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type
ACPI_FUNCTION_TRACE(acpi_disable_gpe);
- /* Parameter validation */
-
- if (!gpe_type || (gpe_type & ~ACPI_GPE_TYPE_WAKE_RUN)) {
- return_ACPI_STATUS(AE_BAD_PARAMETER);
- }
-
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
/* Ensure that we have a valid GPE number */
@@ -440,41 +366,21 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type
/* Hardware-disable a runtime GPE on removal of the last reference */
- if (gpe_type & ACPI_GPE_TYPE_RUNTIME) {
- if (!gpe_event_info->runtime_count) {
- status = AE_LIMIT; /* There are no references to remove */
- goto unlock_and_exit;
- }
-
- gpe_event_info->runtime_count--;
- if (!gpe_event_info->runtime_count) {
- status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
- if (ACPI_SUCCESS(status)) {
- status = acpi_hw_low_set_gpe(gpe_event_info,
- ACPI_GPE_DISABLE);
- }
-
- if (ACPI_FAILURE(status)) {
- gpe_event_info->runtime_count++;
- goto unlock_and_exit;
- }
- }
+ if (!gpe_event_info->runtime_count) {
+ status = AE_LIMIT; /* There are no references to remove */
+ goto unlock_and_exit;
}
- /*
- * Update masks for wake GPE on removal of the last reference.
- * No need to hardware-disable wake GPEs here, they are not currently
- * enabled.
- */
- if (gpe_type & ACPI_GPE_TYPE_WAKE) {
- if (!gpe_event_info->wakeup_count) {
- status = AE_LIMIT; /* There are no references to remove */
- goto unlock_and_exit;
+ gpe_event_info->runtime_count--;
+ if (!gpe_event_info->runtime_count) {
+ status = acpi_ev_update_gpe_enable_mask(gpe_event_info);
+ if (ACPI_SUCCESS(status)) {
+ status =
+ acpi_hw_low_set_gpe(gpe_event_info,
+ ACPI_GPE_DISABLE);
}
-
- gpe_event_info->wakeup_count--;
- if (!gpe_event_info->wakeup_count) {
- status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
+ if (ACPI_FAILURE(status)) {
+ gpe_event_info->runtime_count++;
}
}
@@ -486,6 +392,59 @@ ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
/*******************************************************************************
*
+ * FUNCTION: acpi_gpe_can_wake
+ *
+ * PARAMETERS: 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).
+ *
+ ******************************************************************************/
+acpi_status acpi_gpe_can_wake(acpi_handle gpe_device, u32 gpe_number)
+{
+ acpi_status status = AE_OK;
+ struct acpi_gpe_event_info *gpe_event_info;
+ acpi_cpu_flags flags;
+ u8 disable = 0;
+
+ ACPI_FUNCTION_TRACE(acpi_gpe_can_wake);
+
+ 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 (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) {
+ goto unlock_and_exit;
+ }
+
+ gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
+ disable = (gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD)
+ && gpe_event_info->runtime_count;
+
+unlock_and_exit:
+ acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+
+ if (disable)
+ status = acpi_disable_gpe(gpe_device, gpe_number);
+
+ return_ACPI_STATUS(status);
+}
+ACPI_EXPORT_SYMBOL(acpi_gpe_can_wake)
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_disable_event
*
* PARAMETERS: Event - The fixed eventto be enabled
@@ -800,7 +759,7 @@ acpi_install_gpe_block(acpi_handle gpe_device,
obj_desc->device.gpe_block = gpe_block;
- /* Run the _PRW methods and enable the runtime GPEs in the new block */
+ /* Enable the runtime GPEs in the new block */
status = acpi_ev_initialize_gpe_block(node, gpe_block);