ppc64: Add a `primary' argument to pci_process_bridge_OF_ranges
authorPaul Mackerras <paulus@samba.org>
Sat, 22 Oct 2005 05:03:21 +0000 (15:03 +1000)
committerPaul Mackerras <paulus@samba.org>
Sat, 22 Oct 2005 05:03:21 +0000 (15:03 +1000)
... for consistency with ppc32 and to make the powermac merge easier.
Also make it use just a single resource in the host bridge for multiple
consecutive elements of the ranges property.

Signed-off-by: Paul Mackerras <paulus@samba.org>
arch/ppc64/kernel/maple_pci.c
arch/ppc64/kernel/pci.c
arch/ppc64/kernel/rtas_pci.c
include/asm-ppc64/pci-bridge.h

index b901470f55cc43dfe09d3bd6edc5c2acd8b4d575..633324b5e61b9de893525e9f381dcdf0b9d5c7b6 100644 (file)
@@ -359,7 +359,7 @@ static int __init add_bridge(struct device_node *dev)
 
        /* Interpret the "ranges" property */
        /* This also maps the I/O region and sets isa_io/mem_base */
-       pci_process_bridge_OF_ranges(hose, dev);
+       pci_process_bridge_OF_ranges(hose, dev, primary);
        pci_setup_phb_io(hose, primary);
 
        /* Fixup "bus-range" OF property */
index feec06bbafc3e6ee19ef8e621cb767c9a68df752..b2fb6746f00b0bff6ccced3cb81263fba4398941 100644 (file)
@@ -880,9 +880,9 @@ static void __devinit pci_process_ISA_OF_ranges(struct device_node *isa_node,
 }
 
 void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
-                                           struct device_node *dev)
+                                           struct device_node *dev, int prim)
 {
-       unsigned int *ranges;
+       unsigned int *ranges, pci_space;
        unsigned long size;
        int rlen = 0;
        int memno = 0;
@@ -905,16 +905,39 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
        ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
        while ((rlen -= np * sizeof(unsigned int)) >= 0) {
                res = NULL;
-               pci_addr = (unsigned long)ranges[1] << 32 | ranges[2];
+               pci_space = ranges[0];
+               pci_addr = ((unsigned long)ranges[1] << 32) | ranges[2];
 
                cpu_phys_addr = ranges[3];
-               if (na == 2)
-                       cpu_phys_addr = cpu_phys_addr << 32 | ranges[4];
+               if (na >= 2)
+                       cpu_phys_addr = (cpu_phys_addr << 32) | ranges[4];
 
-               size = (unsigned long)ranges[na+3] << 32 | ranges[na+4];
+               size = ((unsigned long)ranges[na+3] << 32) | ranges[na+4];
+               ranges += np;
                if (size == 0)
                        continue;
-               switch ((ranges[0] >> 24) & 0x3) {
+
+               /* Now consume following elements while they are contiguous */
+               while (rlen >= np * sizeof(unsigned int)) {
+                       unsigned long addr, phys;
+
+                       if (ranges[0] != pci_space)
+                               break;
+                       addr = ((unsigned long)ranges[1] << 32) | ranges[2];
+                       phys = ranges[3];
+                       if (na >= 2)
+                               phys = (phys << 32) | ranges[4];
+                       if (addr != pci_addr + size ||
+                           phys != cpu_phys_addr + size)
+                               break;
+
+                       size += ((unsigned long)ranges[na+3] << 32)
+                               | ranges[na+4];
+                       ranges += np;
+                       rlen -= np * sizeof(unsigned int);
+               }
+
+               switch ((pci_space >> 24) & 0x3) {
                case 1:         /* I/O space */
                        hose->io_base_phys = cpu_phys_addr;
                        hose->pci_io_size = size;
@@ -948,7 +971,6 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
                        res->sibling = NULL;
                        res->child = NULL;
                }
-               ranges += np;
        }
 }
 
index 20361bcd8cfb8b7cf76c297d645ba40915f8be13..3ad15c90fbbd29f55017735666719c96e79a561c 100644 (file)
@@ -400,7 +400,7 @@ unsigned long __init find_and_init_phbs(void)
                if (!phb)
                        continue;
 
-               pci_process_bridge_OF_ranges(phb, node);
+               pci_process_bridge_OF_ranges(phb, node, 0);
                pci_setup_phb_io(phb, index == 0);
 #ifdef CONFIG_PPC_PSERIES
                if (ppc64_interrupt_controller == IC_OPEN_PIC && pSeries_mpic) {
@@ -450,7 +450,7 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
        if (!phb)
                return NULL;
 
-       pci_process_bridge_OF_ranges(phb, dn);
+       pci_process_bridge_OF_ranges(phb, dn, primary);
 
        pci_setup_phb_io_dynamic(phb, primary);
        of_node_put(root);
index 7d8ecb507a3d666c675a2a98c6d2950616aee291..60cf8c838af0df1e36e6d68fdd9c3c3d5c6616af 100644 (file)
@@ -123,7 +123,7 @@ static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
 }
 
 extern void pci_process_bridge_OF_ranges(struct pci_controller *hose,
-                                        struct device_node *dev);
+                                        struct device_node *dev, int primary);
 
 extern int pcibios_remove_root_bus(struct pci_controller *phb);