On Tuesday 09 March 2010 01:56:02 pm Bjorn Helgaas wrote: > http://bugzilla.kernel.org/show_bug.cgi?id=15480 > > This is a regression since 2.6.33. Thanks a lot for the report! > > pci_root PNP0A03:00: host bridge window [io 0x0000-0x0cf7] > pci_root PNP0A03:00: host bridge window [io 0x0d00-0xffff] > pci_root PNP0A03:00: host bridge window [mem 0x000a0000-0x000bffff] > pci_root PNP0A03:00: host bridge window [mem 0x000c0000-0x000dffff] > pci_root PNP0A03:00: host bridge window [mem 0xfed40000-0xfed44fff] > pci_root PNP0A03:00: can't allocate host bridge window [mem 0xcff00000-0x10ed0ffff] > > The last window completely encloses the previous one, which is fine, > so the problem must be that something overlaps *part* of that last > window. My guess is that the conflict is with a System RAM area, possibly one starting at 0x100000000 like the one here: http://fixunix.com/debian/514784-bug-492865-installation-report-mostly-good-some-gripes-about-partitioning-installer-error-mesgs.html That feels like a BIOS bug in the host bridge description, since accesses to the conflict area will probably go to RAM, not to PCI. Can you try the attached debug patch and report the dmesg output? If this makes your system boot, we'll have to think about whether this is the right workaround, and whether and how we'd want to get the conflicting resource out of kernel/resource.c. There are no other interfaces there that return the conflict resource, so maybe there's a reason for keeping them internal. Bjorn commit db86a01c1dd7d0a6c18e1b9edd479c1e6a08de93 Author: Bjorn Helgaas <bjorn.helgaas@xxxxxx> Date: Tue Mar 9 11:43:17 2010 -0700 diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 6e22454..42d8f01 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -118,7 +118,7 @@ static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data) { struct pci_root_info *info = data; - struct resource *res; + struct resource *res, *conflict; struct acpi_resource_address64 addr; acpi_status status; unsigned long flags; @@ -157,21 +157,39 @@ setup_resource(struct acpi_resource *acpi_res, void *data) return AE_OK; } - if (insert_resource(root, res)) { + for (;;) { + conflict = insert_resource_conflict(root, res); + if (!conflict) + break; + dev_err(&info->bridge->dev, - "can't allocate host bridge window %pR\n", res); - } else { - pci_bus_add_resource(info->bus, res, 0); - info->res_num++; - if (addr.translation_offset) - dev_info(&info->bridge->dev, "host bridge window %pR " - "(PCI address [%#llx-%#llx])\n", - res, res->start - addr.translation_offset, - res->end - addr.translation_offset); - else - dev_info(&info->bridge->dev, - "host bridge window %pR\n", res); + "host bridge window %pR conflicts with %pR\n", + res, conflict); + if (res->start < conflict->end && conflict->end < res->end) + res->start = conflict->end + 1; + if (res->start < conflict->start && conflict->start < res->end) + res->end = conflict->start - 1; + + if (res->start >= res->end) { + dev_err(&info->bridge->dev, + "can't allocate host bridge window\n"); + return AE_OK; + } + + dev_info(&info->bridge->dev, + "host bridge window trimmed to %pR\n", res); } + + pci_bus_add_resource(info->bus, res, 0); + info->res_num++; + if (addr.translation_offset) + dev_info(&info->bridge->dev, "host bridge window %pR " + "(PCI address [%#llx-%#llx])\n", + res, res->start - addr.translation_offset, + res->end - addr.translation_offset); + else + dev_info(&info->bridge->dev, + "host bridge window %pR\n", res); return AE_OK; } diff --git a/include/linux/ioport.h b/include/linux/ioport.h index dda9841..9f88526 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -117,6 +117,7 @@ extern void reserve_region_with_split(struct resource *root, resource_size_t start, resource_size_t end, const char *name); extern int insert_resource(struct resource *parent, struct resource *new); +extern struct resource *insert_resource_conflict(struct resource *parent, struct resource *new); extern void insert_resource_expand_to_fit(struct resource *root, struct resource *new); extern int allocate_resource(struct resource *root, struct resource *new, resource_size_t size, resource_size_t min, diff --git a/kernel/resource.c b/kernel/resource.c index 2d5be5d..8ec71a2 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -496,6 +496,16 @@ int insert_resource(struct resource *parent, struct resource *new) return conflict ? -EBUSY : 0; } +struct resource *insert_resource_conflict(struct resource *parent, struct resource *new) +{ + struct resource *conflict; + + write_lock(&resource_lock); + conflict = __insert_resource(parent, new); + write_unlock(&resource_lock); + return conflict; +} + /** * insert_resource_expand_to_fit - Insert a resource into the resource tree * @root: root resource descriptor -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html