mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-18 10:13:57 +08:00
ACPI / ACPICA: Defer enabling of runtime GPEs (v3)
The current ACPI GPEs initialization code has a problem that it enables some GPEs pointed to by device _PRW methods, generally intended for signaling wakeup events (system or device wakeup). These GPEs are then almost immediately disabled by the ACPI namespace scanning code with the help of acpi_gpe_can_wake(), but it would be better not to enable them at all until really necessary. Modify the initialization of GPEs so that the ones that have associated _Lxx or _Exx methods and are not pointed to by any _PRW methods will be enabled after the namespace scan is complete. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Len Brown <len.brown@intel.com>
This commit is contained in:
parent
2422084a94
commit
a210080195
@ -105,8 +105,9 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
|
|||||||
struct acpi_gpe_block_info **return_gpe_block);
|
struct acpi_gpe_block_info **return_gpe_block);
|
||||||
|
|
||||||
acpi_status
|
acpi_status
|
||||||
acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
|
acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
|
||||||
struct acpi_gpe_block_info *gpe_block);
|
struct acpi_gpe_block_info *gpe_block,
|
||||||
|
void *ignored);
|
||||||
|
|
||||||
acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block);
|
acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block);
|
||||||
|
|
||||||
|
@ -364,6 +364,7 @@ ACPI_EXTERN struct acpi_fixed_event_handler
|
|||||||
ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head;
|
ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head;
|
||||||
ACPI_EXTERN struct acpi_gpe_block_info
|
ACPI_EXTERN struct acpi_gpe_block_info
|
||||||
*acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS];
|
*acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS];
|
||||||
|
ACPI_EXTERN u8 acpi_all_gpes_initialized;
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
|
@ -413,6 +413,7 @@ struct acpi_handler_info {
|
|||||||
void *context; /* Context to be passed to handler */
|
void *context; /* Context to be passed to handler */
|
||||||
struct acpi_namespace_node *method_node; /* Method node for this GPE level (saved) */
|
struct acpi_namespace_node *method_node; /* Method node for this GPE level (saved) */
|
||||||
u8 orig_flags; /* Original misc info about this GPE */
|
u8 orig_flags; /* Original misc info about this GPE */
|
||||||
|
u8 orig_enabled; /* Set if the GPE was originally enabled */
|
||||||
};
|
};
|
||||||
|
|
||||||
union acpi_gpe_dispatch_info {
|
union acpi_gpe_dispatch_info {
|
||||||
@ -457,6 +458,7 @@ struct acpi_gpe_block_info {
|
|||||||
u32 register_count; /* Number of register pairs in block */
|
u32 register_count; /* Number of register pairs in block */
|
||||||
u16 gpe_count; /* Number of individual GPEs in block */
|
u16 gpe_count; /* Number of individual GPEs in block */
|
||||||
u8 block_base_number; /* Base GPE number for this block */
|
u8 block_base_number; /* Base GPE number for this block */
|
||||||
|
u8 initialized; /* If set, the GPE block has been initialized */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Information about GPE interrupt handlers, one per each interrupt level used for GPEs */
|
/* Information about GPE interrupt handlers, one per each interrupt level used for GPEs */
|
||||||
@ -473,7 +475,6 @@ struct acpi_gpe_walk_info {
|
|||||||
struct acpi_gpe_block_info *gpe_block;
|
struct acpi_gpe_block_info *gpe_block;
|
||||||
u16 count;
|
u16 count;
|
||||||
acpi_owner_id owner_id;
|
acpi_owner_id owner_id;
|
||||||
u8 enable_this_gpe;
|
|
||||||
u8 execute_by_owner_id;
|
u8 execute_by_owner_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -93,47 +93,6 @@ acpi_status acpi_ev_initialize_events(void)
|
|||||||
return_ACPI_STATUS(status);
|
return_ACPI_STATUS(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
*
|
|
||||||
* FUNCTION: acpi_ev_install_fadt_gpes
|
|
||||||
*
|
|
||||||
* PARAMETERS: None
|
|
||||||
*
|
|
||||||
* RETURN: Status
|
|
||||||
*
|
|
||||||
* DESCRIPTION: Completes initialization of the FADT-defined GPE blocks
|
|
||||||
* (0 and 1). The HW must be fully initialized at this point,
|
|
||||||
* including global lock support.
|
|
||||||
*
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
acpi_status acpi_ev_install_fadt_gpes(void)
|
|
||||||
{
|
|
||||||
acpi_status status;
|
|
||||||
|
|
||||||
ACPI_FUNCTION_TRACE(ev_install_fadt_gpes);
|
|
||||||
|
|
||||||
/* Namespace must be locked */
|
|
||||||
|
|
||||||
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
|
|
||||||
if (ACPI_FAILURE(status)) {
|
|
||||||
return (status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FADT GPE Block 0 */
|
|
||||||
|
|
||||||
(void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device,
|
|
||||||
acpi_gbl_gpe_fadt_blocks[0]);
|
|
||||||
|
|
||||||
/* FADT GPE Block 1 */
|
|
||||||
|
|
||||||
(void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device,
|
|
||||||
acpi_gbl_gpe_fadt_blocks[1]);
|
|
||||||
|
|
||||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
|
||||||
return_ACPI_STATUS(AE_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
*
|
*
|
||||||
* FUNCTION: acpi_ev_install_xrupt_handlers
|
* FUNCTION: acpi_ev_install_xrupt_handlers
|
||||||
|
@ -363,6 +363,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
|
|||||||
gpe_block->gpe_count = (u16)(register_count * ACPI_GPE_REGISTER_WIDTH);
|
gpe_block->gpe_count = (u16)(register_count * ACPI_GPE_REGISTER_WIDTH);
|
||||||
gpe_block->register_count = register_count;
|
gpe_block->register_count = register_count;
|
||||||
gpe_block->block_base_number = gpe_block_base_number;
|
gpe_block->block_base_number = gpe_block_base_number;
|
||||||
|
gpe_block->initialized = FALSE;
|
||||||
|
|
||||||
ACPI_MEMCPY(&gpe_block->block_address, gpe_block_address,
|
ACPI_MEMCPY(&gpe_block->block_address, gpe_block_address,
|
||||||
sizeof(struct acpi_generic_address));
|
sizeof(struct acpi_generic_address));
|
||||||
@ -385,11 +386,12 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
|
|||||||
return_ACPI_STATUS(status);
|
return_ACPI_STATUS(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
acpi_all_gpes_initialized = FALSE;
|
||||||
|
|
||||||
/* Find all GPE methods (_Lxx or_Exx) for this block */
|
/* Find all GPE methods (_Lxx or_Exx) for this block */
|
||||||
|
|
||||||
walk_info.gpe_block = gpe_block;
|
walk_info.gpe_block = gpe_block;
|
||||||
walk_info.gpe_device = gpe_device;
|
walk_info.gpe_device = gpe_device;
|
||||||
walk_info.enable_this_gpe = FALSE;
|
|
||||||
walk_info.execute_by_owner_id = FALSE;
|
walk_info.execute_by_owner_id = FALSE;
|
||||||
|
|
||||||
status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device,
|
status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device,
|
||||||
@ -434,35 +436,34 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
acpi_status
|
acpi_status
|
||||||
acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
|
acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
|
||||||
struct acpi_gpe_block_info *gpe_block)
|
struct acpi_gpe_block_info *gpe_block,
|
||||||
|
void *ignored)
|
||||||
{
|
{
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
struct acpi_gpe_event_info *gpe_event_info;
|
struct acpi_gpe_event_info *gpe_event_info;
|
||||||
u32 gpe_enabled_count;
|
u32 gpe_enabled_count;
|
||||||
u32 gpe_index;
|
u32 gpe_index;
|
||||||
u32 gpe_number;
|
|
||||||
u32 i;
|
u32 i;
|
||||||
u32 j;
|
u32 j;
|
||||||
|
|
||||||
ACPI_FUNCTION_TRACE(ev_initialize_gpe_block);
|
ACPI_FUNCTION_TRACE(ev_initialize_gpe_block);
|
||||||
|
|
||||||
/* Ignore a null GPE block (e.g., if no GPE block 1 exists) */
|
/*
|
||||||
|
* Ignore a null GPE block (e.g., if no GPE block 1 exists) and
|
||||||
if (!gpe_block) {
|
* GPE blocks that have been initialized already.
|
||||||
|
*/
|
||||||
|
if (!gpe_block || gpe_block->initialized) {
|
||||||
return_ACPI_STATUS(AE_OK);
|
return_ACPI_STATUS(AE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enable all GPEs that have a corresponding method. Any other GPEs
|
* Enable all GPEs that have a corresponding method and have the
|
||||||
* within this block must be enabled via the acpi_enable_gpe interface.
|
* ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block must
|
||||||
|
* be enabled via the acpi_enable_gpe() interface.
|
||||||
*/
|
*/
|
||||||
gpe_enabled_count = 0;
|
gpe_enabled_count = 0;
|
||||||
|
|
||||||
if (gpe_device == acpi_gbl_fadt_gpe_device) {
|
|
||||||
gpe_device = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < gpe_block->register_count; i++) {
|
for (i = 0; i < gpe_block->register_count; i++) {
|
||||||
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
|
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
|
||||||
|
|
||||||
@ -470,27 +471,19 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
|
|||||||
|
|
||||||
gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;
|
gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;
|
||||||
gpe_event_info = &gpe_block->event_info[gpe_index];
|
gpe_event_info = &gpe_block->event_info[gpe_index];
|
||||||
gpe_number = gpe_index + gpe_block->block_base_number;
|
|
||||||
|
|
||||||
/* Ignore GPEs that have no corresponding _Lxx/_Exx method */
|
/* Ignore GPEs that have no corresponding _Lxx/_Exx method */
|
||||||
|
|
||||||
if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD)) {
|
if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD)
|
||||||
|
|| (gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
status = acpi_raw_enable_gpe(gpe_event_info);
|
||||||
* If the GPE has already been enabled for runtime
|
|
||||||
* signaling, make sure it remains enabled, but do not
|
|
||||||
* increment its reference counter.
|
|
||||||
*/
|
|
||||||
status = gpe_event_info->runtime_count ?
|
|
||||||
acpi_ev_enable_gpe(gpe_event_info) :
|
|
||||||
acpi_enable_gpe(gpe_device, gpe_number);
|
|
||||||
|
|
||||||
if (ACPI_FAILURE(status)) {
|
if (ACPI_FAILURE(status)) {
|
||||||
ACPI_EXCEPTION((AE_INFO, status,
|
ACPI_EXCEPTION((AE_INFO, status,
|
||||||
"Could not enable GPE 0x%02X",
|
"Could not enable GPE 0x%02X",
|
||||||
gpe_number));
|
gpe_index + gpe_block->block_base_number));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,5 +497,7 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
|
|||||||
gpe_enabled_count));
|
gpe_enabled_count));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gpe_block->initialized = TRUE;
|
||||||
|
|
||||||
return_ACPI_STATUS(AE_OK);
|
return_ACPI_STATUS(AE_OK);
|
||||||
}
|
}
|
||||||
|
@ -210,8 +210,7 @@ acpi_status acpi_ev_gpe_initialize(void)
|
|||||||
*
|
*
|
||||||
* DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a
|
* DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a
|
||||||
* result of a Load() or load_table() operation. If new GPE
|
* result of a Load() or load_table() operation. If new GPE
|
||||||
* methods have been installed, register the new methods and
|
* methods have been installed, register the new methods.
|
||||||
* enable and runtime GPEs that are associated with them.
|
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
@ -239,7 +238,6 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id)
|
|||||||
walk_info.owner_id = table_owner_id;
|
walk_info.owner_id = table_owner_id;
|
||||||
walk_info.execute_by_owner_id = TRUE;
|
walk_info.execute_by_owner_id = TRUE;
|
||||||
walk_info.count = 0;
|
walk_info.count = 0;
|
||||||
walk_info.enable_this_gpe = TRUE;
|
|
||||||
|
|
||||||
/* Walk the interrupt level descriptor list */
|
/* Walk the interrupt level descriptor list */
|
||||||
|
|
||||||
@ -301,8 +299,6 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id)
|
|||||||
*
|
*
|
||||||
* If walk_info->execute_by_owner_id is TRUE, we only execute examine GPE methods
|
* If walk_info->execute_by_owner_id is TRUE, we only execute examine GPE methods
|
||||||
* with that owner.
|
* with that owner.
|
||||||
* If walk_info->enable_this_gpe is TRUE, the GPE that is referred to by a GPE
|
|
||||||
* method is immediately enabled (Used for Load/load_table operators)
|
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
@ -315,8 +311,6 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,
|
|||||||
struct acpi_gpe_walk_info *walk_info =
|
struct acpi_gpe_walk_info *walk_info =
|
||||||
ACPI_CAST_PTR(struct acpi_gpe_walk_info, context);
|
ACPI_CAST_PTR(struct acpi_gpe_walk_info, context);
|
||||||
struct acpi_gpe_event_info *gpe_event_info;
|
struct acpi_gpe_event_info *gpe_event_info;
|
||||||
struct acpi_namespace_node *gpe_device;
|
|
||||||
acpi_status status;
|
|
||||||
u32 gpe_number;
|
u32 gpe_number;
|
||||||
char name[ACPI_NAME_SIZE + 1];
|
char name[ACPI_NAME_SIZE + 1];
|
||||||
u8 type;
|
u8 type;
|
||||||
@ -421,29 +415,6 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,
|
|||||||
gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD);
|
gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD);
|
||||||
gpe_event_info->dispatch.method_node = method_node;
|
gpe_event_info->dispatch.method_node = method_node;
|
||||||
|
|
||||||
/*
|
|
||||||
* Enable this GPE if requested. This only happens when during the
|
|
||||||
* execution of a Load or load_table operator. We have found a new
|
|
||||||
* GPE method and want to immediately enable the GPE if it is a
|
|
||||||
* runtime GPE.
|
|
||||||
*/
|
|
||||||
if (walk_info->enable_this_gpe) {
|
|
||||||
|
|
||||||
walk_info->count++;
|
|
||||||
gpe_device = walk_info->gpe_device;
|
|
||||||
|
|
||||||
if (gpe_device == acpi_gbl_fadt_gpe_device) {
|
|
||||||
gpe_device = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = acpi_enable_gpe(gpe_device, gpe_number);
|
|
||||||
if (ACPI_FAILURE(status)) {
|
|
||||||
ACPI_EXCEPTION((AE_INFO, status,
|
|
||||||
"Could not enable GPE 0x%02X",
|
|
||||||
gpe_number));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
|
ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
|
||||||
"Registered GPE method %s as GPE number 0x%.2X\n",
|
"Registered GPE method %s as GPE number 0x%.2X\n",
|
||||||
name, gpe_number));
|
name, gpe_number));
|
||||||
|
@ -726,15 +726,16 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
|
|||||||
(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
|
(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the GPE is associated with a method and it cannot wake up the
|
* If the GPE is associated with a method, it might have been enabled
|
||||||
* system from sleep states, it was enabled automatically during
|
* automatically during initialization, in which case it has to be
|
||||||
* initialization, so it has to be disabled now to avoid spurious
|
* disabled now to avoid spurious execution of the handler.
|
||||||
* execution of the handler.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD)
|
if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD)
|
||||||
&& !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE))
|
&& gpe_event_info->runtime_count) {
|
||||||
|
handler->orig_enabled = 1;
|
||||||
(void)acpi_raw_disable_gpe(gpe_event_info);
|
(void)acpi_raw_disable_gpe(gpe_event_info);
|
||||||
|
}
|
||||||
|
|
||||||
/* Install the handler */
|
/* Install the handler */
|
||||||
|
|
||||||
@ -837,13 +838,13 @@ acpi_remove_gpe_handler(acpi_handle gpe_device,
|
|||||||
gpe_event_info->flags |= handler->orig_flags;
|
gpe_event_info->flags |= handler->orig_flags;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the GPE was previously associated with a method and it cannot wake
|
* If the GPE was previously associated with a method and it was
|
||||||
* up the system from sleep states, it should be enabled at this point
|
* enabled, it should be enabled at this point to restore the
|
||||||
* to restore the post-initialization configuration.
|
* post-initialization configuration.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD)
|
if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD)
|
||||||
&& !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE))
|
&& handler->orig_enabled)
|
||||||
(void)acpi_raw_enable_gpe(gpe_event_info);
|
(void)acpi_raw_enable_gpe(gpe_event_info);
|
||||||
|
|
||||||
/* Now we can free the handler object */
|
/* Now we can free the handler object */
|
||||||
|
@ -379,21 +379,12 @@ acpi_status acpi_gpe_can_wake(acpi_handle gpe_device, u32 gpe_number)
|
|||||||
/* Ensure that we have a valid GPE number */
|
/* Ensure that we have a valid GPE number */
|
||||||
|
|
||||||
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
|
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
|
||||||
if (!gpe_event_info) {
|
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;
|
gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
|
||||||
if (gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD) {
|
} else {
|
||||||
(void)acpi_raw_disable_gpe(gpe_event_info);
|
status = AE_BAD_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock_and_exit:
|
|
||||||
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
|
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
|
||||||
return_ACPI_STATUS(status);
|
return_ACPI_STATUS(status);
|
||||||
}
|
}
|
||||||
@ -651,7 +642,7 @@ acpi_install_gpe_block(acpi_handle gpe_device,
|
|||||||
struct acpi_generic_address *gpe_block_address,
|
struct acpi_generic_address *gpe_block_address,
|
||||||
u32 register_count, u32 interrupt_number)
|
u32 register_count, u32 interrupt_number)
|
||||||
{
|
{
|
||||||
acpi_status status;
|
acpi_status status = AE_OK;
|
||||||
union acpi_operand_object *obj_desc;
|
union acpi_operand_object *obj_desc;
|
||||||
struct acpi_namespace_node *node;
|
struct acpi_namespace_node *node;
|
||||||
struct acpi_gpe_block_info *gpe_block;
|
struct acpi_gpe_block_info *gpe_block;
|
||||||
@ -715,10 +706,6 @@ acpi_install_gpe_block(acpi_handle gpe_device,
|
|||||||
|
|
||||||
obj_desc->device.gpe_block = gpe_block;
|
obj_desc->device.gpe_block = gpe_block;
|
||||||
|
|
||||||
/* Enable the runtime GPEs in the new block */
|
|
||||||
|
|
||||||
status = acpi_ev_initialize_gpe_block(node, gpe_block);
|
|
||||||
|
|
||||||
unlock_and_exit:
|
unlock_and_exit:
|
||||||
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
|
||||||
return_ACPI_STATUS(status);
|
return_ACPI_STATUS(status);
|
||||||
@ -924,3 +911,43 @@ acpi_status acpi_enable_all_runtime_gpes(void)
|
|||||||
|
|
||||||
return_ACPI_STATUS(status);
|
return_ACPI_STATUS(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* FUNCTION: acpi_update_gpes
|
||||||
|
*
|
||||||
|
* PARAMETERS: None
|
||||||
|
*
|
||||||
|
* RETURN: None
|
||||||
|
*
|
||||||
|
* DESCRIPTION: Enable all GPEs that have associated _Lxx or _Exx methods and
|
||||||
|
* are not pointed to by any device _PRW methods indicating that
|
||||||
|
* these GPEs are generally intended for system or device wakeup
|
||||||
|
* (such GPEs have to be enabled directly when the devices whose
|
||||||
|
* _PRW methods point to them are set up for wakeup signaling).
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
acpi_status acpi_update_gpes(void)
|
||||||
|
{
|
||||||
|
acpi_status status;
|
||||||
|
|
||||||
|
ACPI_FUNCTION_TRACE(acpi_update_gpes);
|
||||||
|
|
||||||
|
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
return_ACPI_STATUS(status);
|
||||||
|
} else if (acpi_all_gpes_initialized) {
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block, NULL);
|
||||||
|
if (ACPI_SUCCESS(status)) {
|
||||||
|
acpi_all_gpes_initialized = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
|
||||||
|
|
||||||
|
return_ACPI_STATUS(status);
|
||||||
|
}
|
||||||
|
@ -766,6 +766,7 @@ acpi_status acpi_ut_init_globals(void)
|
|||||||
acpi_gbl_gpe_fadt_blocks[0] = NULL;
|
acpi_gbl_gpe_fadt_blocks[0] = NULL;
|
||||||
acpi_gbl_gpe_fadt_blocks[1] = NULL;
|
acpi_gbl_gpe_fadt_blocks[1] = NULL;
|
||||||
acpi_current_gpe_count = 0;
|
acpi_current_gpe_count = 0;
|
||||||
|
acpi_all_gpes_initialized = FALSE;
|
||||||
|
|
||||||
/* Global handlers */
|
/* Global handlers */
|
||||||
|
|
||||||
|
@ -289,19 +289,6 @@ acpi_status acpi_initialize_objects(u32 flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Complete the GPE initialization for the GPE blocks defined in the FADT
|
|
||||||
* (GPE block 0 and 1).
|
|
||||||
*
|
|
||||||
* NOTE: Currently, there seems to be no need to run the _REG methods
|
|
||||||
* before enabling the GPEs.
|
|
||||||
*/
|
|
||||||
if (!(flags & ACPI_NO_EVENT_INIT)) {
|
|
||||||
status = acpi_ev_install_fadt_gpes();
|
|
||||||
if (ACPI_FAILURE(status))
|
|
||||||
return (status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Empty the caches (delete the cached objects) on the assumption that
|
* Empty the caches (delete the cached objects) on the assumption that
|
||||||
* the table load filled them up more than they will be at runtime --
|
* the table load filled them up more than they will be at runtime --
|
||||||
|
@ -725,6 +725,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
|
|||||||
complete_dock(ds);
|
complete_dock(ds);
|
||||||
dock_event(ds, event, DOCK_EVENT);
|
dock_event(ds, event, DOCK_EVENT);
|
||||||
dock_lock(ds, 1);
|
dock_lock(ds, 1);
|
||||||
|
acpi_update_gpes();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (dock_present(ds) || dock_in_progress(ds))
|
if (dock_present(ds) || dock_in_progress(ds))
|
||||||
|
@ -1431,6 +1431,7 @@ EXPORT_SYMBOL(acpi_bus_add);
|
|||||||
int acpi_bus_start(struct acpi_device *device)
|
int acpi_bus_start(struct acpi_device *device)
|
||||||
{
|
{
|
||||||
struct acpi_bus_ops ops;
|
struct acpi_bus_ops ops;
|
||||||
|
int result;
|
||||||
|
|
||||||
if (!device)
|
if (!device)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -1438,7 +1439,11 @@ int acpi_bus_start(struct acpi_device *device)
|
|||||||
memset(&ops, 0, sizeof(ops));
|
memset(&ops, 0, sizeof(ops));
|
||||||
ops.acpi_op_start = 1;
|
ops.acpi_op_start = 1;
|
||||||
|
|
||||||
return acpi_bus_scan(device->handle, &ops, NULL);
|
result = acpi_bus_scan(device->handle, &ops, NULL);
|
||||||
|
|
||||||
|
acpi_update_gpes();
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(acpi_bus_start);
|
EXPORT_SYMBOL(acpi_bus_start);
|
||||||
|
|
||||||
@ -1552,6 +1557,8 @@ int __init acpi_scan_init(void)
|
|||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
|
acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
|
||||||
|
else
|
||||||
|
acpi_update_gpes();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -308,6 +308,8 @@ acpi_install_gpe_block(acpi_handle gpe_device,
|
|||||||
|
|
||||||
acpi_status acpi_remove_gpe_block(acpi_handle gpe_device);
|
acpi_status acpi_remove_gpe_block(acpi_handle gpe_device);
|
||||||
|
|
||||||
|
acpi_status acpi_update_gpes(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Resource interfaces
|
* Resource interfaces
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user