]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/ppc64/kernel/pSeries_iommu.c
[PATCH] PPC64: Fix boot for some pre-POWER4 systems
[linux-2.6-omap-h63xx.git] / arch / ppc64 / kernel / pSeries_iommu.c
index f0fd7fbd6531cd01fb8984d2c81e82a25825b484..8c6313e7e1453658980fa4ddb8ac0b9755216fb7 100644 (file)
@@ -265,8 +265,10 @@ static void iommu_table_setparms(struct pci_controller *phb,
        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(struct pci_controller *phb,
 
 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 = PCI_DN(dn);
+
+       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;
+       }
+
+       /* Check if the ISA bus on the system is under
+        * this PHB.
         */
+       isa_dn = isa_dn_orig = of_find_node_by_type(NULL, "isa");
 
-       dn = pci_bus_to_OF_node(bus);
-       pci = dn->data;
-
-       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;
-                       }
-
-                       tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
-
-                       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;
-
-                       tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
-
-                       iommu_table_setparms(pci->phb, dn, tbl);
-                       pci->iommu_table = iommu_init_table(tbl);
-
-                       /* All child buses have 256MB tables */
-                       pci->phb->dma_window_size = 1 << 28;
-               }
-       } else {
-               pdn = pci_bus_to_OF_node(bus->parent);
+       while (isa_dn && isa_dn != dn)
+               isa_dn = isa_dn->parent;
+
+       if (isa_dn_orig)
+               of_node_put(isa_dn_orig);
 
-               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.
-                        */
+       /* 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++;
 
-                       tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
+       DBG("Children: %d\n", children);
 
-                       iommu_table_setparms(pci->phb, dn, tbl);
+       /* 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.
+        */
 
-                       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;
-               }
+       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;
+
+               return;
        }
+
+       /* 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;
+
+       tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
+
+       iommu_table_setparms(pci->phb, dn, tbl);
+       pci->iommu_table = iommu_init_table(tbl);
+
+       /* 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;
+
+       DBG("ISA/IDE, window size is %x\n", pci->phb->dma_window_size);
+
 }
 
 
@@ -446,14 +440,29 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus)
 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;