[PATCH 5/8] ACPI: acpi_tb_parse_root_table supports inactive tables

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



support parsing the inactive root table in acpi_tb_parse_root_table.

Signed-off-by: Zhang Rui <rui.zhang@xxxxxxxxx>
---
 drivers/acpi/tables/tbutils.c |  137 +++++++++++++++++++++++++-----------------
 1 file changed, 84 insertions(+), 53 deletions(-)

Index: linux-2.6/drivers/acpi/tables/tbutils.c
===================================================================
--- linux-2.6.orig/drivers/acpi/tables/tbutils.c
+++ linux-2.6/drivers/acpi/tables/tbutils.c
@@ -426,59 +426,78 @@ acpi_tb_parse_root_table(acpi_physical_a
 	u32 table_count;
 	struct acpi_table_header *table;
 	acpi_physical_address address;
-	acpi_physical_address uninitialized_var(rsdt_address);
+	acpi_physical_address rsdt_address, xsdt_address = 0;
+	static acpi_physical_address inactive_table_root_pointer;
+	static u32 inactive_table_entry_size;
+	struct acpi_internal_rsdt *root_table_list = get_root_table_list(flags);
 	u32 length;
 	u8 *table_entry;
 	acpi_status status;
 
 	ACPI_FUNCTION_TRACE(tb_parse_root_table);
 
-	/*
-	 * Map the entire RSDP and extract the address of the RSDT or XSDT
-	 */
-	rsdp = acpi_os_map_memory(rsdp_address, sizeof(struct acpi_table_rsdp));
-	if (!rsdp) {
-		return_ACPI_STATUS(AE_NO_MEMORY);
-	}
-
-	acpi_tb_print_table_header(rsdp_address,
-				   ACPI_CAST_PTR(struct acpi_table_header,
-						 rsdp));
-
-	/* Differentiate between RSDT and XSDT root tables */
-
-	if (rsdp->revision > 1 && rsdp->xsdt_physical_address) {
+	if (TABLE_IS_ACTIVE(flags)) {
 		/*
-		 * Root table is an XSDT (64-bit physical addresses). We must use the
-		 * XSDT if the revision is > 1 and the XSDT pointer is present, as per
-		 * the ACPI specification.
+		 * Map RSDP and extract the address of the RSDT or XSDT
 		 */
-		address = (acpi_physical_address) rsdp->xsdt_physical_address;
-		table_entry_size = sizeof(u64);
-		rsdt_address = (acpi_physical_address)
-					rsdp->rsdt_physical_address;
-	} else {
-		/* Root table is an RSDT (32-bit physical addresses) */
-
-		address = (acpi_physical_address) rsdp->rsdt_physical_address;
-		table_entry_size = sizeof(u32);
-	}
-
-	/*
-	 * It is not possible to map more than one entry in some environments,
-	 * so unmap the RSDP here before mapping other tables
-	 */
-	acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp));
-
-	if (table_entry_size == sizeof(u64)) {
-		if (acpi_tb_check_xsdt(address) == AE_NULL_ENTRY) {
-			/* XSDT has NULL entry, RSDT is used */
+		rsdp = acpi_os_map_memory(rsdp_address,
+					sizeof(struct acpi_table_rsdp));
+		if (!rsdp)
+			return_ACPI_STATUS(AE_NO_MEMORY);
+
+		acpi_tb_print_table_header(rsdp_address,
+				ACPI_CAST_PTR(struct acpi_table_header,
+				rsdp));
+
+		/* Differentiate between RSDT and XSDT root tables */
+
+		rsdt_address =
+			(acpi_physical_address) rsdp->rsdt_physical_address;
+		if (rsdp->revision > 1 && rsdp->xsdt_physical_address) {
+			/*
+			 * Root table is an XSDT (64-bit physical addresses).
+			 * We must use the XSDT if the revision is > 1 and the
+			 * XSDT pointer is present, per the ACPI specification.
+			 */
+			xsdt_address = (acpi_physical_address)
+						rsdp->xsdt_physical_address;
+			address = xsdt_address;
+			table_entry_size = sizeof(u64);
+		} else {
+			/* Root table is an RSDT (32-bit physical addresses) */
+			xsdt_address = 0;
 			address = rsdt_address;
 			table_entry_size = sizeof(u32);
-			ACPI_WARNING((AE_INFO, "BIOS XSDT has NULL entry, "
-					"using RSDT"));
 		}
+
+		/*
+		 * It's not possible to map more than one entry in some
+		 * environments, so unmap the RSDP before mapping other tables
+		 */
+		acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp));
+
+		if (table_entry_size == sizeof(u64)) {
+			if (acpi_tb_check_xsdt(address) == AE_NULL_ENTRY) {
+				/* XSDT has NULL entry, RSDT is used */
+				address = rsdt_address;
+				table_entry_size = sizeof(u32);
+				ACPI_WARNING((AE_INFO, "XSDT has NULL entry, "
+						"using RSDT"));
+			}
+		}
+
+		inactive_table_root_pointer =
+			(address == rsdt_address ? xsdt_address : rsdt_address);
+		inactive_table_entry_size =
+					(table_entry_size == sizeof(u32) ?
+					sizeof(u64) : sizeof(u32));
+	} else {
+		if (!inactive_table_root_pointer)
+			return AE_NO_ACPI_TABLES;
+		address = inactive_table_root_pointer;
+		table_entry_size = inactive_table_entry_size;
 	}
+
 	/* Map the RSDT/XSDT table header to get the full table length */
 
 	table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
@@ -486,7 +505,8 @@ acpi_tb_parse_root_table(acpi_physical_a
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
 
-	acpi_tb_print_table_header(address, table);
+	if (TABLE_IS_ACTIVE(flags))
+		acpi_tb_print_table_header(address, table);
 
 	/* Get the length of the full table, verify length and map entire table */
 
@@ -524,15 +544,26 @@ acpi_tb_parse_root_table(acpi_physical_a
 	 */
 	table_entry =
 	    ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header);
-	acpi_gbl_root_table_list.count = 2;
+	root_table_list->count = 2;
+
+	/* allocate memory for the inactive root table list */
+	if (!TABLE_IS_ACTIVE(flags)) {
+		if (!root_table_list->tables) {
+			root_table_list->size =
+				root_table_list->count + table_count;
+			root_table_list->tables = ACPI_ALLOCATE_ZEROED(
+					sizeof(struct acpi_table_desc) *
+					root_table_list->size);
+		}
+	}
 
 	/*
 	 * Initialize the root table array from the RSDT/XSDT
 	 */
 	for (i = 0; i < table_count; i++) {
-		if (acpi_gbl_root_table_list.count >=
-		    acpi_gbl_root_table_list.size) {
-
+		if (root_table_list->count >= root_table_list->size) {
+			if (!TABLE_IS_ACTIVE(flags))
+				break;
 			/* There is no more room in the root table array, attempt resize */
 
 			status = acpi_tb_resize_root_table_list();
@@ -549,12 +580,12 @@ acpi_tb_parse_root_table(acpi_physical_a
 
 		/* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */
 
-		acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
-		    address =
-		    acpi_tb_get_root_table_entry(table_entry, table_entry_size);
+		root_table_list->tables[root_table_list->count].address =
+				acpi_tb_get_root_table_entry(
+					table_entry, table_entry_size);
 
 		table_entry += table_entry_size;
-		acpi_gbl_root_table_list.count++;
+		root_table_list->count++;
 	}
 
 	/*
@@ -567,15 +598,15 @@ acpi_tb_parse_root_table(acpi_physical_a
 	 * Complete the initialization of the root table array by examining
 	 * the header of each table
 	 */
-	for (i = 2, table_count = acpi_gbl_root_table_list.count;
+	for (i = 2, table_count = root_table_list->count;
 		i < table_count; i++) {
-		acpi_tb_install_table(acpi_gbl_root_table_list.tables[i].
+		acpi_tb_install_table(root_table_list->tables[i].
 				      address, flags, NULL, i);
 
 		/* Special case for FADT - get the DSDT and FACS */
 
 		if (ACPI_COMPARE_NAME
-		    (&acpi_gbl_root_table_list.tables[i].signature,
+		    (&root_table_list->tables[i].signature,
 		     ACPI_SIG_FADT)) {
 			acpi_tb_parse_fadt(i, flags);
 		}


--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux