[PATCH] PPC64: Fix boot for some pre-POWER4 systems

Olof Johansson olof at lixom.net
Sun Sep 18 06:00:46 EST 2005


Hi,

I suggest this to be included in 2.6.14 for two reasons:

1. While the bug has been there a couple of releases, it does keep some
users machines from booting and this resolves it.

2. In case of regressions caused by this patch, this is in code that is
only used in non-partitioned POWER4 or older systems. PowerMac, Maple,
iSeries and any POWER5 system is using other ways of determining any
iommu table partitioning. I.e. it's not affecting the majority of the
PPC64 user base.


----

Some RS64 systems (such as F80) have non-python host bridges with EADS.
However, they have two EADS with 4 buses each under them, so the old logic
that assumed no more than 7 busses per PHB failed miserably.

Big thanks to Olaf Hering for helping me test this, he's got one of the
few machines that broke from the previous logic.

Also, to be a bit smarter at detecting the need for a PHB-level IOMMU
table by checking for the presence of an ISA bus. Only PHBs with ISA
bridges should need the PHB-level table.

Signed-off-by: Olof Johansson <olof at lixom.net>

Index: 2.6/arch/ppc64/kernel/pSeries_iommu.c
===================================================================
--- 2.6.orig/arch/ppc64/kernel/pSeries_iommu.c	2005-09-14 17:45:56.000000000 -0500
+++ 2.6/arch/ppc64/kernel/pSeries_iommu.c	2005-09-14 18:04:02.000000000 -0500
@@ -265,8 +265,10 @@ static void iommu_table_setparms(struct 
 	tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT;
 	
 	/* Test if we are going over 2GB of DMA space */
-	if (phb->dma_window_base_cur + phb->dma_window_size > (1L << 31))
+	if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) {
+		udbg_printf("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); 
 		panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); 
+	}
 	
 	phb->dma_window_base_cur += phb->dma_window_size;
 
@@ -310,92 +312,84 @@ static void iommu_table_setparms_lpar(st
 
 static void iommu_bus_setup_pSeries(struct pci_bus *bus)
 {
-	struct device_node *dn, *pdn;
-	struct pci_dn *pci;
+	struct device_node *dn;
 	struct iommu_table *tbl;
+	struct device_node *isa_dn, *isa_dn_orig;
+	struct device_node *tmp;
+	struct pci_dn *pci;
+	int children;
 
 	DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self);
 
-	/* For each (root) bus, we carve up the available DMA space in 256MB
-	 * pieces. Since each piece is used by one (sub) bus/device, that would
-	 * give a maximum of 7 devices per PHB. In most cases, this is plenty.
-	 *
-	 * The exception is on Python PHBs (pre-POWER4). Here we don't have EADS
-	 * bridges below the PHB to allocate the sectioned tables to, so instead
-	 * we allocate a 1GB table at the PHB level.
-	 */
-
 	dn = pci_bus_to_OF_node(bus);
-	pci = dn->data;
+	pci = PCI_DN(dn);
 
-	if (!bus->self) {
-		/* Root bus */
-		if (is_python(dn)) {
-			unsigned int *iohole;
-
-			DBG("Python root bus %s\n", bus->name);
-
-			iohole = (unsigned int *)get_property(dn, "io-hole", 0);
-
-			if (iohole) {
-				/* On first bus we need to leave room for the
-				 * ISA address space. Just skip the first 256MB
-				 * alltogether. This leaves 768MB for the window.
-				 */
-				DBG("PHB has io-hole, reserving 256MB\n");
-				pci->phb->dma_window_size = 3 << 28;
-				pci->phb->dma_window_base_cur = 1 << 28;
-			} else {
-				/* 1GB window by default */
-				pci->phb->dma_window_size = 1 << 30;
-				pci->phb->dma_window_base_cur = 0;
-			}
+	if (bus->self) {
+		/* This is not a root bus, any setup will be done for the
+		 * device-side of the bridge in iommu_dev_setup_pSeries().
+		 */
+		return;
+	}
 
-			tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
+	/* Check if the ISA bus on the system is under
+	 * this PHB.
+	 */
+	isa_dn = isa_dn_orig = of_find_node_by_type(NULL, "isa");
+ 
+	while (isa_dn && isa_dn != dn)
+		isa_dn = isa_dn->parent;
+
+	if (isa_dn_orig)
+		of_node_put(isa_dn_orig);
+
+	/* Count number of direct PCI children of the PHB.
+	 * All PCI device nodes have class-code property, so it's
+	 * an easy way to find them.
+	 */
+	for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling)
+		if (get_property(tmp, "class-code", NULL))
+			children++;
+ 
+	DBG("Children: %d\n", children);
+ 
+	/* Calculate amount of DMA window per slot. Each window must be
+	 * a power of two (due to pci_alloc_consistent requirements).
+	 *
+	 * Keep 256MB aside for PHBs with ISA.
+	 */
 
-			iommu_table_setparms(pci->phb, dn, tbl);
-			pci->iommu_table = iommu_init_table(tbl);
-		} else {
-			/* Do a 128MB table at root. This is used for the IDE
-			 * controller on some SMP-mode POWER4 machines. It
-			 * doesn't hurt to allocate it on other machines
-			 * -- it'll just be unused since new tables are
-			 * allocated on the EADS level.
-			 *
-			 * Allocate at offset 128MB to avoid having to deal
-			 * with ISA holes; 128MB table for IDE is plenty.
-			 */
-			pci->phb->dma_window_size = 1 << 27;
-			pci->phb->dma_window_base_cur = 1 << 27;
+	if (!isa_dn) {
+		/* No ISA/IDE - just set window size and return */
+		pci->phb->dma_window_size = 0x80000000ul; /* To be divided */
+ 
+		while (pci->phb->dma_window_size * children > 0x80000000ul)
+			pci->phb->dma_window_size >>= 1;
+		DBG("No ISA/IDE, window size is %x\n", pci->phb->dma_window_size);
+		pci->phb->dma_window_base_cur = 0;
 
-			tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
+		return;
+	}
 
-			iommu_table_setparms(pci->phb, dn, tbl);
-			pci->iommu_table = iommu_init_table(tbl);
+	/* If we have ISA, then we probably have an IDE
+	 * controller too. Allocate a 128MB table but
+	 * skip the first 128MB to avoid stepping on ISA
+	 * space.
+	 */
+	pci->phb->dma_window_size = 0x8000000ul;
+	pci->phb->dma_window_base_cur = 0x8000000ul;
 
-			/* All child buses have 256MB tables */
-			pci->phb->dma_window_size = 1 << 28;
-		}
-	} else {
-		pdn = pci_bus_to_OF_node(bus->parent);
+	tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
 
-		if (!bus->parent->self && !is_python(pdn)) {
-			struct iommu_table *tbl;
-			/* First child and not python means this is the EADS
-			 * level. Allocate new table for this slot with 256MB
-			 * window.
-			 */
+	iommu_table_setparms(pci->phb, dn, tbl);
+	pci->iommu_table = iommu_init_table(tbl);
 
-			tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
+	/* Divide the rest (1.75GB) among the children */
+	pci->phb->dma_window_size = 0x80000000ul;
+	while (pci->phb->dma_window_size * children > 0x70000000ul)
+		pci->phb->dma_window_size >>= 1;
 
-			iommu_table_setparms(pci->phb, dn, tbl);
+	DBG("ISA/IDE, window size is %x\n", pci->phb->dma_window_size);
 
-			pci->iommu_table = iommu_init_table(tbl);
-		} else {
-			/* Lower than first child or under python, use parent table */
-			pci->iommu_table = PCI_DN(pdn)->iommu_table;
-		}
-	}
 }
 
 
@@ -446,14 +440,29 @@ static void iommu_bus_setup_pSeriesLP(st
 static void iommu_dev_setup_pSeries(struct pci_dev *dev)
 {
 	struct device_node *dn, *mydn;
+	struct iommu_table *tbl;
 
 	DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, dev->pretty_name);
-	/* Now copy the iommu_table ptr from the bus device down to the
-	 * pci device_node.  This means get_iommu_table() won't need to search
-	 * up the device tree to find it.
-	 */
+ 
 	mydn = dn = pci_device_to_OF_node(dev);
 
+	/* If we're the direct child of a root bus, then we need to allocate
+	 * an iommu table ourselves. The bus setup code should have setup
+	 * the window sizes already.
+	 */
+	if (!dev->bus->self) {
+		DBG(" --> first child, no bridge. Allocating iommu table.\n");
+		tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
+		iommu_table_setparms(PCI_DN(dn)->phb, dn, tbl);
+		PCI_DN(mydn)->iommu_table = iommu_init_table(tbl);
+
+		return;
+	}
+ 
+	/* If this device is further down the bus tree, search upwards until
+	 * an already allocated iommu table is found and use that.
+	 */
+
 	while (dn && dn->data && PCI_DN(dn)->iommu_table == NULL)
 		dn = dn->parent;
 



More information about the Linuxppc64-dev mailing list