ACPICA: Allow same ACPI table to be loaded/unloaded more than once
authorBob Moore <robert.moore@intel.com>
Fri, 4 Jul 2008 02:48:43 +0000 (10:48 +0800)
committerLen Brown <len.brown@intel.com>
Thu, 23 Oct 2008 03:14:35 +0000 (23:14 -0400)
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 <robert.moore@intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
drivers/acpi/tables/tbinstal.c

index b22185f55a16acf80e9814059acff89a4a1e508b..905dc38ab23b3528d3fbbcaa4f54408e09125383 100644 (file)
@@ -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: