Re: Problems booting 2.6.18 on SunBlade 100/150

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

 



From: Jim Watson <jim@xxxxxxxxxxxxxxx>
Date: Sun, 15 Oct 2006 14:57:58 +1000

> > (arch/sparc64/sparc/time.c) differ in 2.6.16 and 2.6.18. On 2.6.16 it
> > gets
> > mstk48t59_regs=000001ff011800000
> >
> my apologies for the extra digit, this should read:
> 
> mstk48t59_regs=000001ff01800000

Ok, I figured it out.  Please test the patch below as soon as you can,
it seems to work on my SB100.

The bug wasn't introduced by the new code in 2.6.18, rather the new
code in 2.6.18 uncovered an obscure old bug that's been with us
forever :-)

The deal is that on Hummingbird systems like SB100/SB150, the PCI
memory space is the full 32-bit 4GB range, minus the IOMMU translated
area.  In my thinking when writing the Hummingbird support code, I
believed that the IOMMU area would always be at the very top of the
4GB range, but this assumption is incorrect.

For example, the IOMMU DMA range on my SB100 is 0xc0000000 to
0xdfffffff, this means that 0xe0000000-->0xffffffff are valid PCI mem
space mapping areas for devices.  As a consequence of this mistake,
any device mapped by OBP into this upper area would be deemed an
invalid mapping by Linux.  So we'd remap that device somewhere else.

The new OBP device code in 2.6.18 assumes that any mapping created
by the OBP firmware is valid and won't get remapped by the kernel.
And this is what caused the clock to have an incorrect register
address.  If we use the PROM properties to compute the address, as
the new OBP device code does, we miss the fixup the PCI layer does
to the EBUS PCI device which determines the clock register address.
This remapping should never happen in the first place and that's
the bug.

Fix below, and some loosening of the resource conflict message
suppression so we can spot more problems like this in the future.

diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
index 7a59cc7..827ae30 100644
--- a/arch/sparc64/kernel/pci_common.c
+++ b/arch/sparc64/kernel/pci_common.c
@@ -330,19 +330,6 @@ #endif
 	return res;
 }
 
-static int __init pdev_resource_collisions_expected(struct pci_dev *pdev)
-{
-	if (pdev->vendor != PCI_VENDOR_ID_SUN)
-		return 0;
-
-	if (pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS ||
-	    pdev->device == PCI_DEVICE_ID_SUN_RIO_1394 ||
-	    pdev->device == PCI_DEVICE_ID_SUN_RIO_USB)
-		return 1;
-
-	return 0;
-}
-
 static void __init pdev_record_assignments(struct pci_pbm_info *pbm,
 					   struct pci_dev *pdev)
 {
@@ -400,19 +387,23 @@ static void __init pdev_record_assignmen
 		pbm->parent->resource_adjust(pdev, res, root);
 
 		if (request_resource(root, res) < 0) {
+			int rnum;
+
 			/* OK, there is some conflict.  But this is fine
 			 * since we'll reassign it in the fixup pass.
 			 *
-			 * We notify the user that OBP made an error if it
-			 * is a case we don't expect.
+			 * Do not print the warning for ROM resources
+			 * as such a conflict is quite common and
+			 * harmless as the ROM bar is disabled.
 			 */
-			if (!pdev_resource_collisions_expected(pdev)) {
-				printk(KERN_ERR "PCI: Address space collision on region %ld "
+			rnum = (res - &pdev->resource[0]);
+			if (rnum != PCI_ROM_RESOURCE)
+				printk(KERN_ERR "PCI: Resource collision, "
+				       "region %d "
 				       "[%016lx:%016lx] of device %s\n",
-				       (res - &pdev->resource[0]),
+				       rnum,
 				       res->start, res->end,
 				       pci_name(pdev));
-			}
 		}
 	}
 }
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index 6ec5698..de7f785 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -1196,7 +1196,7 @@ static void pbm_register_toplevel_resour
 					    &pbm->mem_space);
 }
 
-static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_begin)
+static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_start, u32 dma_end)
 {
 	struct pci_pbm_info *pbm;
 	struct device_node *node;
@@ -1261,6 +1261,8 @@ static void sabre_pbm_init(struct pci_co
 		node = node->sibling;
 	}
 	if (simbas_found == 0) {
+		struct resource *rp;
+
 		/* No APBs underneath, probably this is a hummingbird
 		 * system.
 		 */
@@ -1302,8 +1304,10 @@ static void sabre_pbm_init(struct pci_co
 		pbm->io_space.end   = pbm->io_space.start + (1UL << 24) - 1UL;
 		pbm->io_space.flags = IORESOURCE_IO;
 
-		pbm->mem_space.start = p->pbm_A.controller_regs + SABRE_MEMSPACE;
-		pbm->mem_space.end   = pbm->mem_space.start + (unsigned long)dma_begin - 1UL;
+		pbm->mem_space.start =
+			(p->pbm_A.controller_regs + SABRE_MEMSPACE);
+		pbm->mem_space.end =
+			(pbm->mem_space.start + ((1UL << 32UL) - 1UL));
 		pbm->mem_space.flags = IORESOURCE_MEM;
 
 		if (request_resource(&ioport_resource, &pbm->io_space) < 0) {
@@ -1315,6 +1319,17 @@ static void sabre_pbm_init(struct pci_co
 			prom_halt();
 		}
 
+		rp = kmalloc(sizeof(*rp), GFP_KERNEL);
+		if (!rp) {
+			prom_printf("Cannot allocate IOMMU resource.\n");
+			prom_halt();
+		}
+		rp->name = "IOMMU";
+		rp->start = pbm->mem_space.start + (unsigned long) dma_start;
+		rp->end = pbm->mem_space.start + (unsigned long) dma_end - 1UL;
+		rp->flags = IORESOURCE_BUSY;
+		request_resource(&pbm->mem_space, rp);
+
 		pci_register_legacy_regions(&pbm->io_space,
 					    &pbm->mem_space);
 	}
@@ -1450,5 +1465,5 @@ void sabre_init(struct device_node *dp, 
 	/*
 	 * Look for APB underneath.
 	 */
-	sabre_pbm_init(p, dp, vdma[0]);
+	sabre_pbm_init(p, dp, vdma[0], vdma[1]);
 }
-
To unsubscribe from this list: send the line "unsubscribe sparclinux" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Kernel Development]     [DCCP]     [Linux ARM Development]     [Linux]     [Photo]     [Yosemite Help]     [Linux ARM Kernel]     [Linux SCSI]     [Linux x86_64]     [Linux Hams]

  Powered by Linux