Re: [Bug 15480] [regression] Gigabyte GA-MA78GM-S2H boot fails without pci=nocrs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux