|
@@ -523,6 +523,69 @@ reject:
|
|
|
|
|
|
static int __initdata known_bridge;
|
|
|
|
|
|
+static int acpi_mcfg_64bit_base_addr __initdata = FALSE;
|
|
|
+
|
|
|
+/* The physical address of the MMCONFIG aperture. Set from ACPI tables. */
|
|
|
+struct acpi_mcfg_allocation *pci_mmcfg_config;
|
|
|
+int pci_mmcfg_config_num;
|
|
|
+
|
|
|
+static int __init acpi_mcfg_oem_check(struct acpi_table_mcfg *mcfg)
|
|
|
+{
|
|
|
+ if (!strcmp(mcfg->header.oem_id, "SGI"))
|
|
|
+ acpi_mcfg_64bit_base_addr = TRUE;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int __init pci_parse_mcfg(struct acpi_table_header *header)
|
|
|
+{
|
|
|
+ struct acpi_table_mcfg *mcfg;
|
|
|
+ unsigned long i;
|
|
|
+ int config_size;
|
|
|
+
|
|
|
+ if (!header)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ mcfg = (struct acpi_table_mcfg *)header;
|
|
|
+
|
|
|
+ /* how many config structures do we have */
|
|
|
+ pci_mmcfg_config_num = 0;
|
|
|
+ i = header->length - sizeof(struct acpi_table_mcfg);
|
|
|
+ while (i >= sizeof(struct acpi_mcfg_allocation)) {
|
|
|
+ ++pci_mmcfg_config_num;
|
|
|
+ i -= sizeof(struct acpi_mcfg_allocation);
|
|
|
+ };
|
|
|
+ if (pci_mmcfg_config_num == 0) {
|
|
|
+ printk(KERN_ERR PREFIX "MMCONFIG has no entries\n");
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
+
|
|
|
+ config_size = pci_mmcfg_config_num * sizeof(*pci_mmcfg_config);
|
|
|
+ pci_mmcfg_config = kmalloc(config_size, GFP_KERNEL);
|
|
|
+ if (!pci_mmcfg_config) {
|
|
|
+ printk(KERN_WARNING PREFIX
|
|
|
+ "No memory for MCFG config tables\n");
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ memcpy(pci_mmcfg_config, &mcfg[1], config_size);
|
|
|
+
|
|
|
+ acpi_mcfg_oem_check(mcfg);
|
|
|
+
|
|
|
+ for (i = 0; i < pci_mmcfg_config_num; ++i) {
|
|
|
+ if ((pci_mmcfg_config[i].address > 0xFFFFFFFF) &&
|
|
|
+ !acpi_mcfg_64bit_base_addr) {
|
|
|
+ printk(KERN_ERR PREFIX
|
|
|
+ "MMCONFIG not in low 4GB of memory\n");
|
|
|
+ kfree(pci_mmcfg_config);
|
|
|
+ pci_mmcfg_config_num = 0;
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static void __init __pci_mmcfg_init(int early)
|
|
|
{
|
|
|
/* MMCONFIG disabled */
|
|
@@ -543,7 +606,7 @@ static void __init __pci_mmcfg_init(int early)
|
|
|
}
|
|
|
|
|
|
if (!known_bridge)
|
|
|
- acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg);
|
|
|
+ acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
|
|
|
|
|
|
pci_mmcfg_reject_broken(early);
|
|
|
|