|
@@ -52,6 +52,8 @@ ACPI_MODULE_NAME("evgpe")
|
|
/* Local prototypes */
|
|
/* Local prototypes */
|
|
static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context);
|
|
static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context);
|
|
|
|
|
|
|
|
+static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context);
|
|
|
|
+
|
|
/*******************************************************************************
|
|
/*******************************************************************************
|
|
*
|
|
*
|
|
* FUNCTION: acpi_ev_update_gpe_enable_mask
|
|
* FUNCTION: acpi_ev_update_gpe_enable_mask
|
|
@@ -441,17 +443,25 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
|
|
* an interrupt handler.
|
|
* an interrupt handler.
|
|
*
|
|
*
|
|
******************************************************************************/
|
|
******************************************************************************/
|
|
-static void acpi_ev_asynch_enable_gpe(void *context);
|
|
|
|
|
|
|
|
static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
|
|
static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
|
|
{
|
|
{
|
|
- struct acpi_gpe_event_info *gpe_event_info = (void *)context;
|
|
|
|
|
|
+ struct acpi_gpe_event_info *gpe_event_info = context;
|
|
acpi_status status;
|
|
acpi_status status;
|
|
- struct acpi_gpe_event_info local_gpe_event_info;
|
|
|
|
|
|
+ struct acpi_gpe_event_info *local_gpe_event_info;
|
|
struct acpi_evaluate_info *info;
|
|
struct acpi_evaluate_info *info;
|
|
|
|
|
|
ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method);
|
|
ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method);
|
|
|
|
|
|
|
|
+ /* Allocate a local GPE block */
|
|
|
|
+
|
|
|
|
+ local_gpe_event_info =
|
|
|
|
+ ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_event_info));
|
|
|
|
+ if (!local_gpe_event_info) {
|
|
|
|
+ ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, "while handling a GPE"));
|
|
|
|
+ return_VOID;
|
|
|
|
+ }
|
|
|
|
+
|
|
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
|
|
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
|
|
if (ACPI_FAILURE(status)) {
|
|
if (ACPI_FAILURE(status)) {
|
|
return_VOID;
|
|
return_VOID;
|
|
@@ -468,7 +478,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
|
|
* Take a snapshot of the GPE info for this level - we copy the info to
|
|
* Take a snapshot of the GPE info for this level - we copy the info to
|
|
* prevent a race condition with remove_handler/remove_block.
|
|
* prevent a race condition with remove_handler/remove_block.
|
|
*/
|
|
*/
|
|
- ACPI_MEMCPY(&local_gpe_event_info, gpe_event_info,
|
|
|
|
|
|
+ ACPI_MEMCPY(local_gpe_event_info, gpe_event_info,
|
|
sizeof(struct acpi_gpe_event_info));
|
|
sizeof(struct acpi_gpe_event_info));
|
|
|
|
|
|
status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
|
|
status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
|
|
@@ -480,7 +490,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
|
|
* Must check for control method type dispatch one more time to avoid a
|
|
* Must check for control method type dispatch one more time to avoid a
|
|
* race with ev_gpe_install_handler
|
|
* race with ev_gpe_install_handler
|
|
*/
|
|
*/
|
|
- if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) ==
|
|
|
|
|
|
+ if ((local_gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
|
|
ACPI_GPE_DISPATCH_METHOD) {
|
|
ACPI_GPE_DISPATCH_METHOD) {
|
|
|
|
|
|
/* Allocate the evaluation information block */
|
|
/* Allocate the evaluation information block */
|
|
@@ -494,7 +504,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
|
|
* control method that corresponds to this GPE
|
|
* control method that corresponds to this GPE
|
|
*/
|
|
*/
|
|
info->prefix_node =
|
|
info->prefix_node =
|
|
- local_gpe_event_info.dispatch.method_node;
|
|
|
|
|
|
+ local_gpe_event_info->dispatch.method_node;
|
|
info->flags = ACPI_IGNORE_RETURN_VALUE;
|
|
info->flags = ACPI_IGNORE_RETURN_VALUE;
|
|
|
|
|
|
status = acpi_ns_evaluate(info);
|
|
status = acpi_ns_evaluate(info);
|
|
@@ -505,20 +515,41 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
|
|
ACPI_EXCEPTION((AE_INFO, status,
|
|
ACPI_EXCEPTION((AE_INFO, status,
|
|
"while evaluating GPE method [%4.4s]",
|
|
"while evaluating GPE method [%4.4s]",
|
|
acpi_ut_get_node_name
|
|
acpi_ut_get_node_name
|
|
- (local_gpe_event_info.dispatch.
|
|
|
|
|
|
+ (local_gpe_event_info->dispatch.
|
|
method_node)));
|
|
method_node)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
/* Defer enabling of GPE until all notify handlers are done */
|
|
/* Defer enabling of GPE until all notify handlers are done */
|
|
- acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_asynch_enable_gpe,
|
|
|
|
- gpe_event_info);
|
|
|
|
|
|
+
|
|
|
|
+ status = acpi_os_execute(OSL_NOTIFY_HANDLER,
|
|
|
|
+ acpi_ev_asynch_enable_gpe,
|
|
|
|
+ local_gpe_event_info);
|
|
|
|
+ if (ACPI_FAILURE(status)) {
|
|
|
|
+ ACPI_FREE(local_gpe_event_info);
|
|
|
|
+ }
|
|
return_VOID;
|
|
return_VOID;
|
|
}
|
|
}
|
|
|
|
|
|
-static void acpi_ev_asynch_enable_gpe(void *context)
|
|
|
|
|
|
+/*******************************************************************************
|
|
|
|
+ *
|
|
|
|
+ * FUNCTION: acpi_ev_asynch_enable_gpe
|
|
|
|
+ *
|
|
|
|
+ * PARAMETERS: Context (gpe_event_info) - Info for this GPE
|
|
|
|
+ * Callback from acpi_os_execute
|
|
|
|
+ *
|
|
|
|
+ * RETURN: None
|
|
|
|
+ *
|
|
|
|
+ * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
|
|
|
|
+ * complete.
|
|
|
|
+ *
|
|
|
|
+ ******************************************************************************/
|
|
|
|
+
|
|
|
|
+static void ACPI_SYSTEM_XFACE acpi_ev_asynch_enable_gpe(void *context)
|
|
{
|
|
{
|
|
struct acpi_gpe_event_info *gpe_event_info = context;
|
|
struct acpi_gpe_event_info *gpe_event_info = context;
|
|
acpi_status status;
|
|
acpi_status status;
|
|
|
|
+
|
|
if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
|
|
if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
|
|
ACPI_GPE_LEVEL_TRIGGERED) {
|
|
ACPI_GPE_LEVEL_TRIGGERED) {
|
|
/*
|
|
/*
|
|
@@ -527,7 +558,7 @@ static void acpi_ev_asynch_enable_gpe(void *context)
|
|
*/
|
|
*/
|
|
status = acpi_hw_clear_gpe(gpe_event_info);
|
|
status = acpi_hw_clear_gpe(gpe_event_info);
|
|
if (ACPI_FAILURE(status)) {
|
|
if (ACPI_FAILURE(status)) {
|
|
- return_VOID;
|
|
|
|
|
|
+ goto exit;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -537,7 +568,9 @@ static void acpi_ev_asynch_enable_gpe(void *context)
|
|
*/
|
|
*/
|
|
(void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_CONDITIONAL_ENABLE);
|
|
(void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_CONDITIONAL_ENABLE);
|
|
|
|
|
|
- return_VOID;
|
|
|
|
|
|
+exit:
|
|
|
|
+ ACPI_FREE(gpe_event_info);
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
/*******************************************************************************
|