From e56f561736e340a4e923b0db65f65dabf5d94823 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Fri, 4 Jul 2008 10:48:43 +0800 Subject: [PATCH] ACPICA: Allow same ACPI table to be loaded/unloaded more than once Without this change, a table cannot be loaded again once it has been loaded/unloaded one time. The current mechanism does not unregister a table upon an unload. During a load, if the same table is found, this no longer returns an exception. http://www.acpica.org/bugzilla/show_bug.cgi?id=722 Signed-off-by: Bob Moore Signed-off-by: Lin Ming Signed-off-by: Andi Kleen Signed-off-by: Len Brown --- drivers/acpi/tables/tbinstal.c | 47 +++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c index b22185f55a16..905dc38ab23b 100644 --- a/drivers/acpi/tables/tbinstal.c +++ b/drivers/acpi/tables/tbinstal.c @@ -145,6 +145,8 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) } } + /* Check for a table match on the entire table length */ + length = ACPI_MIN(table_desc->length, acpi_gbl_root_table_list.tables[i].length); if (ACPI_MEMCMP(table_desc->pointer, @@ -153,17 +155,49 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) continue; } - /* Table is already registered */ + /* + * Note: the current mechanism does not unregister a table if it is + * dynamically unloaded. The related namespace entries are deleted, + * but the table remains in the root table list. + * + * The assumption here is that the number of different tables that + * will be loaded is actually small, and there is minimal overhead + * in just keeping the table in case it is needed again. + * + * If this assumption changes in the future (perhaps on large + * machines with many table load/unload operations), tables will + * need to be unregistered when they are unloaded, and slots in the + * root table list should be reused when empty. + */ + /* + * Table is already registered. + * We can delete the table that was passed as a parameter. + */ acpi_tb_delete_table(table_desc); *table_index = i; - status = AE_ALREADY_EXISTS; - goto release; + + if (acpi_gbl_root_table_list.tables[i]. + flags & ACPI_TABLE_IS_LOADED) { + + /* Table is still loaded, this is an error */ + + status = AE_ALREADY_EXISTS; + goto release; + } else { + /* Table was unloaded, allow it to be reloaded */ + + table_desc->pointer = + acpi_gbl_root_table_list.tables[i].pointer; + table_desc->address = + acpi_gbl_root_table_list.tables[i].address; + status = AE_OK; + goto print_header; + } } - /* - * Add the table to the global table list - */ + /* Add the table to the global root table list */ + status = acpi_tb_store_table(table_desc->address, table_desc->pointer, table_desc->length, table_desc->flags, table_index); @@ -171,6 +205,7 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) goto release; } + print_header: acpi_tb_print_table_header(table_desc->address, table_desc->pointer); release: