patch-2.3.99-pre7 linux/arch/i386/kernel/acpi.c

Next file: linux/arch/i386/kernel/apic.c
Previous file: linux/arch/i386/defconfig
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.99-pre6/linux/arch/i386/kernel/acpi.c linux/arch/i386/kernel/acpi.c
@@ -144,14 +144,21 @@
 
 struct acpi_errata_info
 {
-	const char *oem;
-	const char *oem_table;
-	u32 oem_rev;
-	unsigned long options;
+	const char *signature; // table signature (eg. "RSDT")
+	const char *oem;       // OEM name
+	const char *oem_table; // OEM table identifier (optional)
+	u32 oem_rev;           // OEM table revision (optional)
+	unsigned long options; // errata options
 };
 
+/*
+ * We must identify systems that need ACPI_TRUST_TABLES solely from the
+ * RSDP ("RSD PTR ").  All other options should be flagged from the
+ * RSDT ("RSDT") which can be better identified.
+ */
 struct acpi_errata_info acpi_errata[] =
 {
+	{"RSD PTR ", "AMI   ", NULL, 0, ACPI_TRUST_TABLES | ACPI_COPY_TABLES},
 	{NULL, NULL, 0, 0},
 };
 
@@ -521,6 +528,51 @@
 }
 
 /*
+ * Match ACPI table and set options based on platform errata, if any
+ */
+static int __init acpi_find_errata(struct acpi_table *table)
+{
+	struct acpi_errata_info *info;
+	int size;
+
+	for (info = acpi_errata; info->signature && info->oem; info++) {
+		size = strlen(info->signature);
+		if (memcmp(&table->signature, info->signature, size))
+			continue;
+		if (strcmp(info->signature, "RSD PTR ")) {
+			// ordinary ACPI table
+			size = strlen(info->oem);
+			if (memcmp(table->oem, info->oem, size))
+				continue;
+			if (info->oem_table) {
+				size = strlen(info->oem_table);
+				if (memcmp(table->oem_table,
+					   info->oem_table,
+					   size))
+					continue;
+			}
+			if (info->oem_rev && table->oem_rev != info->oem_rev)
+				continue;
+		}
+		else {
+			// special handling for RSDP
+			size = strlen(info->oem);
+			if (memcmp(((struct acpi_rsdp*) table)->oem,
+				   info->oem,
+				   size))
+				continue;
+		}
+
+		printk(KERN_INFO
+		       "ACPI: found platform errata 0x%08lx\n",
+		       info->options);
+		acpi_opts |= info->options;
+		return 0;
+	}
+	return -1;
+}
+
+/*
  * Locate and map ACPI tables
  */
 static int __init acpi_find_tables(void)
@@ -556,6 +608,14 @@
 	if (i >= ACPI_BIOS_ROM_END)
 		return -ENODEV;
 
+	// find any errata based on the RSDP
+	if (!acpi_find_errata((struct acpi_table*) rsdp)) {
+		if (acpi_opts & ACPI_DISABLED)
+			return -EINVAL;
+		else if (acpi_opts & ACPI_CHIPSET_ONLY)
+			return -ENODEV;
+	}
+
 	// fetch RSDT from RSDP
 	rsdt = acpi_map_table(rsdp->rsdt);
 	if (!rsdt) {
@@ -569,6 +629,15 @@
 		acpi_unmap_table(rsdt);
 		return -EINVAL;
 	}
+
+	// find any errata based on the RSDT
+	if (!acpi_find_errata(rsdt)) {
+		if (acpi_opts & ACPI_DISABLED)
+			return -EINVAL;
+		else if (acpi_opts & ACPI_CHIPSET_ONLY)
+			return -ENODEV;
+	}
+
 	// search RSDT for FACP
 	acpi_facp.table = NULL;
 	rsdt_entry = (u32 *) (rsdt + 1);
@@ -631,11 +700,7 @@
 	if (!(pmregmisc & ACPI_PIIX4_PMIOSE))
 		return -ENODEV;
 	
-	pci_read_config_dword(dev, 0x40, &base);
-	if (!(base & PCI_BASE_ADDRESS_SPACE_IO))
-		return -ENODEV;
-	
-	base &= PCI_BASE_ADDRESS_IO_MASK;
+	base = dev->resource[PCI_BRIDGE_RESOURCES].start & PCI_BASE_ADDRESS_IO_MASK;
 	if (!base)
 		return -ENODEV;
 
@@ -688,16 +753,13 @@
 	if (!(tmp & 0x80))
 		return -ENODEV;
 
-	pci_read_config_byte(dev, PCI_CLASS_REVISION, &tmp);
-	tmp = (tmp & 0x10 ? 0x48 : 0x20);
-
-	pci_read_config_dword(dev, tmp, &base);
-	if (!(base & PCI_BASE_ADDRESS_SPACE_IO))
-		return -ENODEV;
-
+	base = pci_resource_start(dev, PCI_BRIDGE_RESOURCES);
+	if (!base) {
+		base = pci_resource_start(dev, PCI_BASE_ADDRESS_4);
+		if (!base)
+			return -ENODEV;
+	}
 	base &= PCI_BASE_ADDRESS_IO_MASK;
-	if (!base)
-		return -ENODEV;
 
 	pci_read_config_byte(dev, 0x42, &irq);
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)