summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Helgaas <bjorn.helgaas@hp.com>2009-10-23 23:20:33 +0200
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-11-04 17:47:22 +0100
commit9a08f7d3506019e3833cd4394ca0d7da0ae3689f (patch)
tree7abb8e68a05ed05d25896b55689df1baf6ec897f
parentx86/PCI/PAT: return EINVAL for pci mmap WC request for !pat_enabled (diff)
downloadlinux-9a08f7d3506019e3833cd4394ca0d7da0ae3689f.tar.xz
linux-9a08f7d3506019e3833cd4394ca0d7da0ae3689f.zip
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.c31
1 files changed, 20 insertions, 11 deletions
diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c
index 602c172d3bd5..02642773c29d 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;