📄 evgpeblk.c
字号:
goto cleanup; } /* Extract pointers from the input context */ gpe_device = gpe_info->gpe_device; gpe_block = gpe_info->gpe_block; /* * The _PRW object must return a package, we are only interested * in the first element */ obj_desc = pkg_desc->package.elements[0]; if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { /* Use FADT-defined GPE device (from definition of _PRW) */ target_gpe_device = acpi_gbl_fadt_gpe_device; /* Integer is the GPE number in the FADT described GPE blocks */ gpe_number = (u32) obj_desc->integer.value; } else if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) { /* Package contains a GPE reference and GPE number within a GPE block */ if ((obj_desc->package.count < 2) || (ACPI_GET_OBJECT_TYPE(obj_desc->package.elements[0]) != ACPI_TYPE_LOCAL_REFERENCE) || (ACPI_GET_OBJECT_TYPE(obj_desc->package.elements[1]) != ACPI_TYPE_INTEGER)) { goto cleanup; } /* Get GPE block reference and decode */ target_gpe_device = obj_desc->package.elements[0]->reference.node; gpe_number = (u32) obj_desc->package.elements[1]->integer.value; } else { /* Unknown type, just ignore it */ goto cleanup; } /* * Is this GPE within this block? * * TRUE iff these conditions are true: * 1) The GPE devices match. * 2) The GPE index(number) is within the range of the Gpe Block * associated with the GPE device. */ if ((gpe_device == target_gpe_device) && (gpe_number >= gpe_block->block_base_number) && (gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) { gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number]; /* Mark GPE for WAKE-ONLY but WAKE_DISABLED */ gpe_event_info->flags &= ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED); status = acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE); if (ACPI_FAILURE(status)) { goto cleanup; } status = acpi_ev_update_gpe_enable_masks(gpe_event_info, ACPI_GPE_DISABLE); } cleanup: acpi_ut_remove_reference(pkg_desc); return_ACPI_STATUS(AE_OK);}/******************************************************************************* * * FUNCTION: acpi_ev_get_gpe_xrupt_block * * PARAMETERS: interrupt_number - Interrupt for a GPE block * * RETURN: A GPE interrupt block * * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt * block per unique interrupt level used for GPEs. * Should be called only when the GPE lists are semaphore locked * and not subject to change. * ******************************************************************************/static struct acpi_gpe_xrupt_info *acpi_ev_get_gpe_xrupt_block(u32 interrupt_number){ struct acpi_gpe_xrupt_info *next_gpe_xrupt; struct acpi_gpe_xrupt_info *gpe_xrupt; acpi_status status; u32 flags; ACPI_FUNCTION_TRACE("ev_get_gpe_xrupt_block"); /* No need for lock since we are not changing any list elements here */ next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head; while (next_gpe_xrupt) { if (next_gpe_xrupt->interrupt_number == interrupt_number) { return_PTR(next_gpe_xrupt); } next_gpe_xrupt = next_gpe_xrupt->next; } /* Not found, must allocate a new xrupt descriptor */ gpe_xrupt = ACPI_MEM_CALLOCATE(sizeof(struct acpi_gpe_xrupt_info)); if (!gpe_xrupt) { return_PTR(NULL); } gpe_xrupt->interrupt_number = interrupt_number; /* Install new interrupt descriptor with spin lock */ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); if (acpi_gbl_gpe_xrupt_list_head) { next_gpe_xrupt = acpi_gbl_gpe_xrupt_list_head; while (next_gpe_xrupt->next) { next_gpe_xrupt = next_gpe_xrupt->next; } next_gpe_xrupt->next = gpe_xrupt; gpe_xrupt->previous = next_gpe_xrupt; } else { acpi_gbl_gpe_xrupt_list_head = gpe_xrupt; } acpi_os_release_lock(acpi_gbl_gpe_lock, flags); /* Install new interrupt handler if not SCI_INT */ if (interrupt_number != acpi_gbl_FADT->sci_int) { status = acpi_os_install_interrupt_handler(interrupt_number, acpi_ev_gpe_xrupt_handler, gpe_xrupt); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Could not install GPE interrupt handler at level 0x%X\n", interrupt_number)); return_PTR(NULL); } } return_PTR(gpe_xrupt);}/******************************************************************************* * * FUNCTION: acpi_ev_delete_gpe_xrupt * * PARAMETERS: gpe_xrupt - A GPE interrupt info block * * RETURN: Status * * DESCRIPTION: Remove and free a gpe_xrupt block. Remove an associated * interrupt handler if not the SCI interrupt. * ******************************************************************************/static acpi_statusacpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt){ acpi_status status; u32 flags; ACPI_FUNCTION_TRACE("ev_delete_gpe_xrupt"); /* We never want to remove the SCI interrupt handler */ if (gpe_xrupt->interrupt_number == acpi_gbl_FADT->sci_int) { gpe_xrupt->gpe_block_list_head = NULL; return_ACPI_STATUS(AE_OK); } /* Disable this interrupt */ status = acpi_os_remove_interrupt_handler(gpe_xrupt->interrupt_number, acpi_ev_gpe_xrupt_handler); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Unlink the interrupt block with lock */ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); if (gpe_xrupt->previous) { gpe_xrupt->previous->next = gpe_xrupt->next; } if (gpe_xrupt->next) { gpe_xrupt->next->previous = gpe_xrupt->previous; } acpi_os_release_lock(acpi_gbl_gpe_lock, flags); /* Free the block */ ACPI_MEM_FREE(gpe_xrupt); return_ACPI_STATUS(AE_OK);}/******************************************************************************* * * FUNCTION: acpi_ev_install_gpe_block * * PARAMETERS: gpe_block - New GPE block * interrupt_number - Xrupt to be associated with this GPE block * * RETURN: Status * * DESCRIPTION: Install new GPE block with mutex support * ******************************************************************************/static acpi_statusacpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block, u32 interrupt_number){ struct acpi_gpe_block_info *next_gpe_block; struct acpi_gpe_xrupt_info *gpe_xrupt_block; acpi_status status; u32 flags; ACPI_FUNCTION_TRACE("ev_install_gpe_block"); status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } gpe_xrupt_block = acpi_ev_get_gpe_xrupt_block(interrupt_number); if (!gpe_xrupt_block) { status = AE_NO_MEMORY; goto unlock_and_exit; } /* Install the new block at the end of the list with lock */ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); if (gpe_xrupt_block->gpe_block_list_head) { next_gpe_block = gpe_xrupt_block->gpe_block_list_head; while (next_gpe_block->next) { next_gpe_block = next_gpe_block->next; } next_gpe_block->next = gpe_block; gpe_block->previous = next_gpe_block; } else { gpe_xrupt_block->gpe_block_list_head = gpe_block; } gpe_block->xrupt_block = gpe_xrupt_block; acpi_os_release_lock(acpi_gbl_gpe_lock, flags); unlock_and_exit: status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status);}/******************************************************************************* * * FUNCTION: acpi_ev_delete_gpe_block * * PARAMETERS: gpe_block - Existing GPE block * * RETURN: Status * * DESCRIPTION: Remove a GPE block * ******************************************************************************/acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block){ acpi_status status; u32 flags; ACPI_FUNCTION_TRACE("ev_install_gpe_block"); status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Disable all GPEs in this block */ status = acpi_hw_disable_gpe_block(gpe_block->xrupt_block, gpe_block); if (!gpe_block->previous && !gpe_block->next) { /* This is the last gpe_block on this interrupt */ status = acpi_ev_delete_gpe_xrupt(gpe_block->xrupt_block); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } } else { /* Remove the block on this interrupt with lock */ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); if (gpe_block->previous) { gpe_block->previous->next = gpe_block->next; } else { gpe_block->xrupt_block->gpe_block_list_head = gpe_block->next; } if (gpe_block->next) { gpe_block->next->previous = gpe_block->previous; } acpi_os_release_lock(acpi_gbl_gpe_lock, flags); } /* Free the gpe_block */ ACPI_MEM_FREE(gpe_block->register_info); ACPI_MEM_FREE(gpe_block->event_info); ACPI_MEM_FREE(gpe_block); unlock_and_exit: status = acpi_ut_release_mutex(ACPI_MTX_EVENTS); return_ACPI_STATUS(status);}/******************************************************************************* * * FUNCTION: acpi_ev_create_gpe_info_blocks * * PARAMETERS: gpe_block - New GPE block * * RETURN: Status * * DESCRIPTION: Create the register_info and event_info blocks for this GPE block * ******************************************************************************/static acpi_statusacpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block){ struct acpi_gpe_register_info *gpe_register_info = NULL; struct acpi_gpe_event_info *gpe_event_info = NULL; struct acpi_gpe_event_info *this_event; struct acpi_gpe_register_info *this_register; acpi_native_uint i; acpi_native_uint j; acpi_status status; ACPI_FUNCTION_TRACE("ev_create_gpe_info_blocks"); /* Allocate the GPE register information block */ gpe_register_info = ACPI_MEM_CALLOCATE((acpi_size) gpe_block-> register_count * sizeof(struct acpi_gpe_register_info)); if (!gpe_register_info) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Could not allocate the gpe_register_info table\n")); return_ACPI_STATUS(AE_NO_MEMORY); } /* * Allocate the GPE event_info block. There are eight distinct GPEs * per register. Initialization to zeros is sufficient. */ gpe_event_info = ACPI_MEM_CALLOCATE(((acpi_size) gpe_block-> register_count * ACPI_GPE_REGISTER_WIDTH) * sizeof(struct acpi_gpe_event_info)); if (!gpe_event_info) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Could not allocate the gpe_event_info table\n")); status = AE_NO_MEMORY;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -