浏览代码

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 <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>
Bob Moore 17 年之前
父节点
当前提交
e56f561736
共有 1 个文件被更改,包括 42 次插入7 次删除
  1. 42 7
      drivers/acpi/tables/tbinstal.c

+ 42 - 7
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,
 		length = ACPI_MIN(table_desc->length,
 				  acpi_gbl_root_table_list.tables[i].length);
 				  acpi_gbl_root_table_list.tables[i].length);
 		if (ACPI_MEMCMP(table_desc->pointer,
 		if (ACPI_MEMCMP(table_desc->pointer,
@@ -153,17 +155,49 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
 			continue;
 			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);
 		acpi_tb_delete_table(table_desc);
 		*table_index = i;
 		*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,
 	status = acpi_tb_store_table(table_desc->address, table_desc->pointer,
 				     table_desc->length, table_desc->flags,
 				     table_desc->length, table_desc->flags,
 				     table_index);
 				     table_index);
@@ -171,6 +205,7 @@ acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
 		goto release;
 		goto release;
 	}
 	}
 
 
+      print_header:
 	acpi_tb_print_table_header(table_desc->address, table_desc->pointer);
 	acpi_tb_print_table_header(table_desc->address, table_desc->pointer);
 
 
       release:
       release: