summaryrefslogtreecommitdiffstats
path: root/arch/ppc64/kernel/pci.c
diff options
context:
space:
mode:
authorPaul Mackerras2005-10-22 07:03:21 +0200
committerPaul Mackerras2005-10-22 07:03:21 +0200
commitf7abbc190b0edec34627d5348ba1d5fa5577da77 (patch)
treedc6a97aaef1cf9174af7e09329db85be0af13c16 /arch/ppc64/kernel/pci.c
parentppc64/powerpc: Fix time initialization on SMP systems (diff)
downloadkernel-qcow2-linux-f7abbc190b0edec34627d5348ba1d5fa5577da77.tar.gz
kernel-qcow2-linux-f7abbc190b0edec34627d5348ba1d5fa5577da77.tar.xz
kernel-qcow2-linux-f7abbc190b0edec34627d5348ba1d5fa5577da77.zip
ppc64: Add a `primary' argument to pci_process_bridge_OF_ranges
... 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>
Diffstat (limited to 'arch/ppc64/kernel/pci.c')
-rw-r--r--arch/ppc64/kernel/pci.c38
1 files changed, 30 insertions, 8 deletions
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
index feec06bbafc3..b2fb6746f00b 100644
--- a/arch/ppc64/kernel/pci.c
+++ b/arch/ppc64/kernel/pci.c
@@ -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;
}
}