diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h index 5fa4b2027697..c569eab774b1 100644 --- a/drivers/acpi/acpica/actables.h +++ b/drivers/acpi/acpica/actables.h @@ -72,13 +72,24 @@ acpi_tb_find_table(char *signature, */ acpi_status acpi_tb_resize_root_table_list(void); -acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc); +acpi_status acpi_tb_validate_table(struct acpi_table_desc *table_desc); -struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header +void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc); + +struct acpi_table_header *acpi_tb_override_table(struct acpi_table_header *table_header, struct acpi_table_desc *table_desc); +acpi_status +acpi_tb_acquire_table(struct acpi_table_desc *table_desc, + struct acpi_table_header **table_ptr, + u32 *table_length, u8 *table_flags); + +void +acpi_tb_release_table(struct acpi_table_header *table, + u32 table_length, u8 table_flags); + acpi_status acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index); @@ -87,7 +98,7 @@ acpi_tb_store_table(acpi_physical_address address, struct acpi_table_header *table, u32 length, u8 flags, u32 *table_index); -void acpi_tb_delete_table(struct acpi_table_desc *table_desc); +void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc); void acpi_tb_terminate(void); diff --git a/drivers/acpi/acpica/tbfind.c b/drivers/acpi/acpica/tbfind.c index c12003947bd5..cb947700206c 100644 --- a/drivers/acpi/acpica/tbfind.c +++ b/drivers/acpi/acpica/tbfind.c @@ -99,8 +99,8 @@ acpi_tb_find_table(char *signature, /* Table is not currently mapped, map it */ status = - acpi_tb_verify_table(&acpi_gbl_root_table_list. - tables[i]); + acpi_tb_validate_table(&acpi_gbl_root_table_list. + tables[i]); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index 0040e19b6d14..93a99ef03425 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -49,49 +49,123 @@ #define _COMPONENT ACPI_TABLES ACPI_MODULE_NAME("tbinstal") -/****************************************************************************** +/******************************************************************************* * - * FUNCTION: acpi_tb_verify_table + * FUNCTION: acpi_tb_acquire_table * - * PARAMETERS: table_desc - table + * PARAMETERS: table_desc - Table descriptor + * table_ptr - Where table is returned + * table_length - Where table length is returned + * table_flags - Where table allocation flags are returned * * RETURN: Status * - * DESCRIPTION: this function is called to verify and map table + * DESCRIPTION: Acquire a table. It can be used for tables not maintained in + * acpi_gbl_root_table_list. + * + ******************************************************************************/ +acpi_status +acpi_tb_acquire_table(struct acpi_table_desc *table_desc, + struct acpi_table_header **table_ptr, + u32 *table_length, u8 *table_flags) +{ + struct acpi_table_header *table = NULL; + + switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { + case ACPI_TABLE_ORIGIN_MAPPED: + + table = + acpi_os_map_memory(table_desc->address, table_desc->length); + break; + + case ACPI_TABLE_ORIGIN_ALLOCATED: + case ACPI_TABLE_ORIGIN_UNKNOWN: + case ACPI_TABLE_ORIGIN_OVERRIDE: + + table = + ACPI_CAST_PTR(struct acpi_table_header, + table_desc->address); + break; + + default: + + break; + } + + /* Table is not valid yet */ + + if (!table) { + return (AE_NO_MEMORY); + } + + /* Fill the return values */ + + *table_ptr = table; + *table_length = table_desc->length; + *table_flags = table_desc->flags; + + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_tb_release_table + * + * PARAMETERS: table - Pointer for the table + * table_length - Length for the table + * table_flags - Allocation flags for the table + * + * RETURN: None + * + * DESCRIPTION: Release a table. The reversal of acpi_tb_acquire_table(). + * + ******************************************************************************/ + +void +acpi_tb_release_table(struct acpi_table_header *table, + u32 table_length, u8 table_flags) +{ + switch (table_flags & ACPI_TABLE_ORIGIN_MASK) { + case ACPI_TABLE_ORIGIN_MAPPED: + + acpi_os_unmap_memory(table, table_length); + break; + + case ACPI_TABLE_ORIGIN_ALLOCATED: + case ACPI_TABLE_ORIGIN_UNKNOWN: + case ACPI_TABLE_ORIGIN_OVERRIDE: + default: + + break; + } +} + +/****************************************************************************** + * + * FUNCTION: acpi_tb_validate_table + * + * PARAMETERS: table_desc - Table descriptor + * + * RETURN: Status + * + * DESCRIPTION: This function is called to validate (ensure Pointer is valid) + * and verify the table. * *****************************************************************************/ -acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc) + +acpi_status acpi_tb_validate_table(struct acpi_table_desc *table_desc) { acpi_status status = AE_OK; - ACPI_FUNCTION_TRACE(tb_verify_table); + ACPI_FUNCTION_TRACE(tb_validate_table); - /* Map the table if necessary */ + /* Validate the table if necessary */ if (!table_desc->pointer) { - switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { - case ACPI_TABLE_ORIGIN_MAPPED: - - table_desc->pointer = - acpi_os_map_memory(table_desc->address, - table_desc->length); - break; - - case ACPI_TABLE_ORIGIN_ALLOCATED: - case ACPI_TABLE_ORIGIN_UNKNOWN: - case ACPI_TABLE_ORIGIN_OVERRIDE: - - table_desc->pointer = - ACPI_CAST_PTR(struct acpi_table_header, - table_desc->address); - break; - - default: - - break; - } - - if (!table_desc->pointer) { + status = acpi_tb_acquire_table(table_desc, &table_desc->pointer, + &table_desc->length, + &table_desc->flags); + if (ACPI_FAILURE(status) || !table_desc->pointer) { return_ACPI_STATUS(AE_NO_MEMORY); } } @@ -104,6 +178,37 @@ acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc) return_ACPI_STATUS(status); } +/******************************************************************************* + * + * FUNCTION: acpi_tb_invalidate_table + * + * PARAMETERS: table_desc - Table descriptor + * + * RETURN: None + * + * DESCRIPTION: Invalidate one internal ACPI table, this is reversal of + * acpi_tb_validate_table(). + * + ******************************************************************************/ + +void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc) +{ + + ACPI_FUNCTION_TRACE(tb_invalidate_table); + + /* Table must be validated */ + + if (!table_desc->pointer) { + return_VOID; + } + + acpi_tb_release_table(table_desc->pointer, table_desc->length, + table_desc->flags); + table_desc->pointer = NULL; + + return_VOID; +} + /******************************************************************************* * * FUNCTION: acpi_tb_add_table @@ -124,11 +229,12 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) { u32 i; acpi_status status = AE_OK; + struct acpi_table_header *final_table; ACPI_FUNCTION_TRACE(tb_add_table); if (!table_desc->pointer) { - status = acpi_tb_verify_table(table_desc); + status = acpi_tb_validate_table(table_desc); if (ACPI_FAILURE(status) || !table_desc->pointer) { return_ACPI_STATUS(status); } @@ -166,8 +272,8 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) { if (!acpi_gbl_root_table_list.tables[i].pointer) { status = - acpi_tb_verify_table(&acpi_gbl_root_table_list. - tables[i]); + acpi_tb_validate_table(&acpi_gbl_root_table_list. + tables[i]); if (ACPI_FAILURE(status) || !acpi_gbl_root_table_list.tables[i].pointer) { continue; @@ -215,7 +321,7 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) } else { /* Table was unloaded, allow it to be reloaded */ - acpi_tb_delete_table(table_desc); + acpi_tb_uninstall_table(table_desc); table_desc->pointer = acpi_gbl_root_table_list.tables[i].pointer; table_desc->address = @@ -229,9 +335,15 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) * ACPI Table Override: * Allow the host to override dynamically loaded tables. * NOTE: the table is fully mapped at this point, and the mapping will - * be deleted by tb_table_override if the table is actually overridden. + * be deleted by acpi_tb_override_table if the table is actually overridden. */ - (void)acpi_tb_table_override(table_desc->pointer, table_desc); + final_table = acpi_tb_override_table(table_desc->pointer, table_desc); + if (final_table) { + + /* Ensure table descriptor is in "VALIDATED" state */ + + table_desc->pointer = final_table; + } /* Add the table to the global root table list */ @@ -252,7 +364,7 @@ release: /******************************************************************************* * - * FUNCTION: acpi_tb_table_override + * FUNCTION: acpi_tb_override_table * * PARAMETERS: table_header - Header for the original table * table_desc - Table descriptor initialized for the @@ -264,29 +376,35 @@ release: * * DESCRIPTION: Attempt table override by calling the OSL override functions. * Note: If the table is overridden, then the entire new table - * is mapped and returned by this function. + * is acquired and returned by this function. + * After invocation, the table descriptor is in a state that is + * "INSTALLED" but not "VALIDATED", thus the "Pointer" member is + * kept NULL. * ******************************************************************************/ -struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header +struct acpi_table_header *acpi_tb_override_table(struct acpi_table_header *table_header, struct acpi_table_desc *table_desc) { acpi_status status; - struct acpi_table_header *new_table = NULL; - acpi_physical_address new_address = 0; - u32 new_table_length = 0; + struct acpi_table_header *new_table; + u32 new_table_length; u8 new_flags; char *override_type; + struct acpi_table_desc new_table_desc; + + ACPI_MEMSET(&new_table_desc, 0, sizeof(struct acpi_table_desc)); /* (1) Attempt logical override (returns a logical address) */ - status = acpi_os_table_override(table_header, &new_table); - if (ACPI_SUCCESS(status) && new_table) { - new_address = ACPI_PTR_TO_PHYSADDR(new_table); - new_table_length = new_table->length; - new_flags = ACPI_TABLE_ORIGIN_OVERRIDE; + status = acpi_os_table_override(table_header, &new_table_desc.pointer); + if (ACPI_SUCCESS(status) && new_table_desc.pointer) { + new_table_desc.address = + ACPI_PTR_TO_PHYSADDR(new_table_desc.pointer); + new_table_desc.length = new_table_desc.pointer->length; + new_table_desc.flags = ACPI_TABLE_ORIGIN_OVERRIDE; override_type = "Logical"; goto finish_override; } @@ -294,25 +412,12 @@ struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header /* (2) Attempt physical override (returns a physical address) */ status = acpi_os_physical_table_override(table_header, - &new_address, - &new_table_length); - if (ACPI_SUCCESS(status) && new_address && new_table_length) { - - /* Map the entire new table */ - - new_table = acpi_os_map_memory(new_address, new_table_length); - if (!new_table) { - ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, - "%4.4s " ACPI_PRINTF_UINT - " Attempted physical table override failed", - table_header->signature, - ACPI_FORMAT_TO_UINT(table_desc-> - address))); - return (NULL); - } - + &new_table_desc.address, + &new_table_desc.length); + if (ACPI_SUCCESS(status) && new_table_desc.address + && new_table_desc.length) { override_type = "Physical"; - new_flags = ACPI_TABLE_ORIGIN_MAPPED; + new_table_desc.flags = ACPI_TABLE_ORIGIN_MAPPED; goto finish_override; } @@ -320,22 +425,36 @@ struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header finish_override: + /* + * Acquire the entire new table to indicate overridden. + * Note that this is required by the callers of this function. + */ + status = acpi_tb_acquire_table(&new_table_desc, &new_table, + &new_table_length, &new_flags); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, + "%4.4s " ACPI_PRINTF_UINT + " Attempted table override failed", + table_header->signature, + ACPI_FORMAT_TO_UINT(table_desc->address))); + return (NULL); + } + ACPI_INFO((AE_INFO, "%4.4s " ACPI_PRINTF_UINT " %s table override, new table: " ACPI_PRINTF_UINT, table_header->signature, ACPI_FORMAT_TO_UINT(table_desc->address), - override_type, ACPI_FORMAT_TO_UINT(new_table))); + override_type, ACPI_FORMAT_TO_UINT(new_table_desc.address))); - /* We can now unmap/delete the original table (if fully mapped) */ + /* We can now uninstall the original table (if fully mapped) */ - acpi_tb_delete_table(table_desc); + acpi_tb_uninstall_table(table_desc); - /* Setup descriptor for the new table */ + /* Install the new table */ - table_desc->address = new_address; - table_desc->pointer = new_table; - table_desc->length = new_table_length; - table_desc->flags = new_flags; + table_desc->address = new_table_desc.address; + table_desc->length = new_table_desc.length; + table_desc->flags = new_table_desc.flags; return (new_table); } @@ -458,9 +577,9 @@ acpi_tb_store_table(acpi_physical_address address, /******************************************************************************* * - * FUNCTION: acpi_tb_delete_table + * FUNCTION: acpi_tb_uninstall_table * - * PARAMETERS: table_index - Table index + * PARAMETERS: table_desc - Table descriptor * * RETURN: None * @@ -468,35 +587,27 @@ acpi_tb_store_table(acpi_physical_address address, * ******************************************************************************/ -void acpi_tb_delete_table(struct acpi_table_desc *table_desc) +void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc) { - /* Table must be mapped or allocated */ + ACPI_FUNCTION_TRACE(tb_uninstall_table); - if (!table_desc->pointer) { - return; + /* Table must be installed */ + + if (!table_desc->address) { + return_VOID; } - switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { - case ACPI_TABLE_ORIGIN_MAPPED: + acpi_tb_invalidate_table(table_desc); - acpi_os_unmap_memory(table_desc->pointer, table_desc->length); - break; - - case ACPI_TABLE_ORIGIN_ALLOCATED: - - ACPI_FREE(table_desc->pointer); - table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL); - break; - - /* Not mapped or allocated, there is nothing we can do */ - - default: - - return; + if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == + ACPI_TABLE_ORIGIN_ALLOCATED) { + ACPI_FREE(ACPI_CAST_PTR(void, table_desc->address)); } - table_desc->pointer = NULL; + table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL); + + return_VOID; } /******************************************************************************* @@ -522,7 +633,7 @@ void acpi_tb_terminate(void) /* Delete the individual tables */ for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) { - acpi_tb_delete_table(&acpi_gbl_root_table_list.tables[i]); + acpi_tb_uninstall_table(&acpi_gbl_root_table_list.tables[i]); } /* diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 9b6992d8578f..c61432fa4332 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -178,7 +178,7 @@ struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index) } ACPI_MEMCPY(new_table, table_desc->pointer, table_desc->length); - acpi_tb_delete_table(table_desc); + acpi_tb_uninstall_table(table_desc); table_desc->address = ACPI_PTR_TO_PHYSADDR(new_table); table_desc->pointer = new_table; table_desc->flags = ACPI_TABLE_ORIGIN_ALLOCATED; @@ -268,7 +268,7 @@ acpi_tb_install_table(acpi_physical_address address, * fully mapped later (in verify table). In any case, we must * unmap the header that was mapped above. */ - final_table = acpi_tb_table_override(table, table_desc); + final_table = acpi_tb_override_table(table, table_desc); if (!final_table) { final_table = table; /* There was no override */ } @@ -290,7 +290,12 @@ acpi_tb_install_table(acpi_physical_address address, * flag set and will not be deleted below. */ if (final_table != table) { - acpi_tb_delete_table(table_desc); + /* + * Table is in "INSTALLED" state, the final_table pointer is not + * maintained in the root table list. + */ + acpi_tb_release_table(final_table, table_desc->length, + table_desc->flags); } unmap_and_exit: diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index 4debc1290d0a..ae3fe4d41137 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -346,7 +346,7 @@ acpi_get_table_with_size(char *signature, } status = - acpi_tb_verify_table(&acpi_gbl_root_table_list.tables[i]); + acpi_tb_validate_table(&acpi_gbl_root_table_list.tables[i]); if (ACPI_SUCCESS(status)) { *out_table = acpi_gbl_root_table_list.tables[i].pointer; *tbl_size = acpi_gbl_root_table_list.tables[i].length; @@ -416,8 +416,8 @@ acpi_get_table_by_index(u32 table_index, struct acpi_table_header ** table) /* Table is not mapped, map it */ status = - acpi_tb_verify_table(&acpi_gbl_root_table_list. - tables[table_index]); + acpi_tb_validate_table(&acpi_gbl_root_table_list. + tables[table_index]); if (ACPI_FAILURE(status)) { (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); return_ACPI_STATUS(status); diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c index 0909420fc776..a2899b0cab23 100644 --- a/drivers/acpi/acpica/tbxfload.c +++ b/drivers/acpi/acpica/tbxfload.c @@ -117,7 +117,7 @@ static acpi_status acpi_tb_load_namespace(void) tables[ACPI_TABLE_INDEX_DSDT].signature), ACPI_SIG_DSDT) || - ACPI_FAILURE(acpi_tb_verify_table + ACPI_FAILURE(acpi_tb_validate_table (&acpi_gbl_root_table_list. tables[ACPI_TABLE_INDEX_DSDT]))) { status = AE_NO_ACPI_TABLES; @@ -128,7 +128,7 @@ static acpi_status acpi_tb_load_namespace(void) * Save the DSDT pointer for simple access. This is the mapped memory * address. We must take care here because the address of the .Tables * array can change dynamically as tables are loaded at run-time. Note: - * .Pointer field is not validated until after call to acpi_tb_verify_table. + * .Pointer field is not validated until after call to acpi_tb_validate_table. */ acpi_gbl_DSDT = acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer; @@ -174,7 +174,7 @@ static acpi_status acpi_tb_load_namespace(void) (acpi_gbl_root_table_list.tables[i]. signature), ACPI_SIG_PSDT)) || - ACPI_FAILURE(acpi_tb_verify_table + ACPI_FAILURE(acpi_tb_validate_table (&acpi_gbl_root_table_list.tables[i]))) { continue; }