diff options
author | Bjorn Helgaas <bjorn.helgaas@hp.com> | 2009-10-23 15:20:33 -0600 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-11-04 08:47:22 -0800 |
commit | 9a08f7d3506019e3833cd4394ca0d7da0ae3689f (patch) | |
tree | 7abb8e68a05ed05d25896b55689df1baf6ec897f | |
parent | 2992e545ea006992ec9dc91c4fa996ce1e15f921 (diff) |
x86/PCI: allow MMCONFIG above 4GB
The current whitelist requires a kernel change for every machine that has
MMCONFIG regions above 4GB, even if BIOS provides a correct MCFG table.
This patch expands the whitelist to include machines with a rev 1 or newer
MCFG table and a DMI_BIOS_DATE of 2010 or later. That way, we only need
kernel changes for new machines that provide incorrect MCFG tables.
Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
CC: Matthew Wilcox <willy@linux.intel.com>
CC: John Keller <jpk@sgi.com>
CC: Yinghai Lu <yhlu.kernel@gmail.com>
CC: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
CC: Andi Kleen <andi@firstfloor.org>
Acked-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-rw-r--r-- | arch/x86/pci/mmconfig-shared.c | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 602c172d3bd..02642773c29 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c @@ -15,6 +15,7 @@ #include <linux/acpi.h> #include <linux/sfi_acpi.h> #include <linux/bitmap.h> +#include <linux/dmi.h> #include <linux/sort.h> #include <asm/e820.h> #include <asm/pci_x86.h> @@ -527,18 +528,31 @@ 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) +static int __init acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg, + struct acpi_mcfg_allocation *cfg) { + int year; + + if (cfg->address < 0xFFFFFFFF) + return 0; + if (!strcmp(mcfg->header.oem_id, "SGI")) - acpi_mcfg_64bit_base_addr = TRUE; + return 0; - return 0; + if (mcfg->header.revision >= 1) { + if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && + year >= 2010) + return 0; + } + + printk(KERN_ERR PREFIX "MCFG region for %04x:%02x-%02x at %#llx " + "is above 4GB, ignored\n", cfg->pci_segment, + cfg->start_bus_number, cfg->end_bus_number, cfg->address); + return -EINVAL; } static int __init pci_parse_mcfg(struct acpi_table_header *header) @@ -574,13 +588,8 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header) 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"); + if (acpi_mcfg_check_entry(mcfg, &pci_mmcfg_config[i])) { kfree(pci_mmcfg_config); pci_mmcfg_config_num = 0; return -ENODEV; |