Commit 7bc5e3f2be32ae6fb0c74cd0f707f986b3a01a26

Authored by Bjorn Helgaas
Committed by Jesse Barnes
1 parent 2fe2abf896

x86/PCI: use host bridge _CRS info by default on 2008 and newer machines

The main benefit of using ACPI host bridge window information is that
we can do better resource allocation in systems with multiple host bridges,
e.g., http://bugzilla.kernel.org/show_bug.cgi?id=14183

Sometimes we need _CRS information even if we only have one host bridge,
e.g., https://bugs.launchpad.net/ubuntu/+source/linux/+bug/341681

Most of these systems are relatively new, so this patch turns on
"pci=use_crs" only on machines with a BIOS date of 2008 or newer.

Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>

Showing 7 changed files with 60 additions and 8 deletions Side-by-side Diff

Documentation/kernel-parameters.txt
... ... @@ -1948,8 +1948,12 @@
1948 1948 IRQ routing is enabled.
1949 1949 noacpi [X86] Do not use ACPI for IRQ routing
1950 1950 or for PCI scanning.
1951   - use_crs [X86] Use _CRS for PCI resource
1952   - allocation.
  1951 + use_crs [X86] Use PCI host bridge window information
  1952 + from ACPI. On BIOSes from 2008 or later, this
  1953 + is enabled by default. If you need to use this,
  1954 + please report a bug.
  1955 + nocrs [X86] Ignore PCI host bridge windows from ACPI.
  1956 + If you need to use this, please report a bug.
1953 1957 routeirq Do IRQ routing for all PCI devices.
1954 1958 This is normally done in pci_enable_device(),
1955 1959 so this option is a temporary workaround
arch/ia64/include/asm/acpi.h
... ... @@ -98,6 +98,7 @@
98 98 #endif
99 99 #define acpi_processor_cstate_check(x) (x) /* no idle limits on IA64 :) */
100 100 static inline void disable_acpi(void) { }
  101 +static inline void pci_acpi_crs_quirks(void) { }
101 102  
102 103 const char *acpi_get_sysname (void);
103 104 int acpi_request_vector (u32 int_type);
arch/x86/include/asm/pci_x86.h
... ... @@ -29,6 +29,7 @@
29 29 #define PCI_CHECK_ENABLE_AMD_MMCONF 0x20000
30 30 #define PCI_HAS_IO_ECS 0x40000
31 31 #define PCI_NOASSIGN_ROMS 0x80000
  32 +#define PCI_ROOT_NO_CRS 0x100000
32 33  
33 34 extern unsigned int pci_probe;
34 35 extern unsigned long pirq_table_addr;
... ... @@ -15,6 +15,51 @@
15 15 int busnum;
16 16 };
17 17  
  18 +static bool pci_use_crs = true;
  19 +
  20 +static int __init set_use_crs(const struct dmi_system_id *id)
  21 +{
  22 + pci_use_crs = true;
  23 + return 0;
  24 +}
  25 +
  26 +static const struct dmi_system_id pci_use_crs_table[] __initconst = {
  27 + /* http://bugzilla.kernel.org/show_bug.cgi?id=14183 */
  28 + {
  29 + .callback = set_use_crs,
  30 + .ident = "IBM System x3800",
  31 + .matches = {
  32 + DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
  33 + DMI_MATCH(DMI_PRODUCT_NAME, "x3800"),
  34 + },
  35 + },
  36 + {}
  37 +};
  38 +
  39 +void __init pci_acpi_crs_quirks(void)
  40 +{
  41 + int year;
  42 +
  43 + if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year < 2008)
  44 + pci_use_crs = false;
  45 +
  46 + dmi_check_system(pci_use_crs_table);
  47 +
  48 + /*
  49 + * If the user specifies "pci=use_crs" or "pci=nocrs" explicitly, that
  50 + * takes precedence over anything we figured out above.
  51 + */
  52 + if (pci_probe & PCI_ROOT_NO_CRS)
  53 + pci_use_crs = false;
  54 + else if (pci_probe & PCI_USE__CRS)
  55 + pci_use_crs = true;
  56 +
  57 + printk(KERN_INFO "PCI: %s host bridge windows from ACPI; "
  58 + "if necessary, use \"pci=%s\" and report a bug\n",
  59 + pci_use_crs ? "Using" : "Ignoring",
  60 + pci_use_crs ? "nocrs" : "use_crs");
  61 +}
  62 +
18 63 static acpi_status
19 64 resource_to_addr(struct acpi_resource *resource,
20 65 struct acpi_resource_address64 *addr)
... ... @@ -106,7 +151,7 @@
106 151 res->child = NULL;
107 152 align_resource(info->bridge, res);
108 153  
109   - if (!(pci_probe & PCI_USE__CRS)) {
  154 + if (!pci_use_crs) {
110 155 dev_printk(KERN_DEBUG, &info->bridge->dev,
111 156 "host bridge window %pR (ignored)\n", res);
112 157 return AE_OK;
113 158  
... ... @@ -137,12 +182,8 @@
137 182 struct pci_root_info info;
138 183 size_t size;
139 184  
140   - if (pci_probe & PCI_USE__CRS)
  185 + if (pci_use_crs)
141 186 pci_bus_remove_resources(bus);
142   - else
143   - dev_info(&device->dev,
144   - "ignoring host bridge windows from ACPI; "
145   - "boot with \"pci=use_crs\" to use them\n");
146 187  
147 188 info.bridge = device;
148 189 info.bus = bus;
arch/x86/pci/common.c
... ... @@ -520,6 +520,9 @@
520 520 } else if (!strcmp(str, "use_crs")) {
521 521 pci_probe |= PCI_USE__CRS;
522 522 return NULL;
  523 + } else if (!strcmp(str, "nocrs")) {
  524 + pci_probe |= PCI_ROOT_NO_CRS;
  525 + return NULL;
523 526 } else if (!strcmp(str, "earlydump")) {
524 527 pci_early_dump_regs = 1;
525 528 return NULL;
drivers/acpi/pci_root.c
... ... @@ -566,6 +566,7 @@
566 566 if (acpi_pci_disabled)
567 567 return 0;
568 568  
  569 + pci_acpi_crs_quirks();
569 570 if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0)
570 571 return -ENODEV;
571 572  
include/acpi/acpi_drivers.h
... ... @@ -104,6 +104,7 @@
104 104  
105 105 struct pci_bus *pci_acpi_scan_root(struct acpi_device *device, int domain,
106 106 int bus);
  107 +void pci_acpi_crs_quirks(void);
107 108  
108 109 /* --------------------------------------------------------------------------
109 110 Processor