aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/ppc64/kernel/maple_pci.c2
-rw-r--r--arch/ppc64/kernel/pci.c38
-rw-r--r--arch/ppc64/kernel/rtas_pci.c4
-rw-r--r--include/asm-ppc64/pci-bridge.h2
4 files changed, 34 insertions, 12 deletions
diff --git a/arch/ppc64/kernel/maple_pci.c b/arch/ppc64/kernel/maple_pci.c
index b901470f55cc..633324b5e61b 100644
--- a/arch/ppc64/kernel/maple_pci.c
+++ b/arch/ppc64/kernel/maple_pci.c
@@ -359,7 +359,7 @@ static int __init add_bridge(struct device_node *dev)
359 359
360 /* Interpret the "ranges" property */ 360 /* Interpret the "ranges" property */
361 /* This also maps the I/O region and sets isa_io/mem_base */ 361 /* This also maps the I/O region and sets isa_io/mem_base */
362 pci_process_bridge_OF_ranges(hose, dev); 362 pci_process_bridge_OF_ranges(hose, dev, primary);
363 pci_setup_phb_io(hose, primary); 363 pci_setup_phb_io(hose, primary);
364 364
365 /* Fixup "bus-range" OF property */ 365 /* Fixup "bus-range" OF property */
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,
880} 880}
881 881
882void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, 882void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
883 struct device_node *dev) 883 struct device_node *dev, int prim)
884{ 884{
885 unsigned int *ranges; 885 unsigned int *ranges, pci_space;
886 unsigned long size; 886 unsigned long size;
887 int rlen = 0; 887 int rlen = 0;
888 int memno = 0; 888 int memno = 0;
@@ -905,16 +905,39 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
905 ranges = (unsigned int *) get_property(dev, "ranges", &rlen); 905 ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
906 while ((rlen -= np * sizeof(unsigned int)) >= 0) { 906 while ((rlen -= np * sizeof(unsigned int)) >= 0) {
907 res = NULL; 907 res = NULL;
908 pci_addr = (unsigned long)ranges[1] << 32 | ranges[2]; 908 pci_space = ranges[0];
909 pci_addr = ((unsigned long)ranges[1] << 32) | ranges[2];
909 910
910 cpu_phys_addr = ranges[3]; 911 cpu_phys_addr = ranges[3];
911 if (na == 2) 912 if (na >= 2)
912 cpu_phys_addr = cpu_phys_addr << 32 | ranges[4]; 913 cpu_phys_addr = (cpu_phys_addr << 32) | ranges[4];
913 914
914 size = (unsigned long)ranges[na+3] << 32 | ranges[na+4]; 915 size = ((unsigned long)ranges[na+3] << 32) | ranges[na+4];
916 ranges += np;
915 if (size == 0) 917 if (size == 0)
916 continue; 918 continue;
917 switch ((ranges[0] >> 24) & 0x3) { 919
920 /* Now consume following elements while they are contiguous */
921 while (rlen >= np * sizeof(unsigned int)) {
922 unsigned long addr, phys;
923
924 if (ranges[0] != pci_space)
925 break;
926 addr = ((unsigned long)ranges[1] << 32) | ranges[2];
927 phys = ranges[3];
928 if (na >= 2)
929 phys = (phys << 32) | ranges[4];
930 if (addr != pci_addr + size ||
931 phys != cpu_phys_addr + size)
932 break;
933
934 size += ((unsigned long)ranges[na+3] << 32)
935 | ranges[na+4];
936 ranges += np;
937 rlen -= np * sizeof(unsigned int);
938 }
939
940 switch ((pci_space >> 24) & 0x3) {
918 case 1: /* I/O space */ 941 case 1: /* I/O space */
919 hose->io_base_phys = cpu_phys_addr; 942 hose->io_base_phys = cpu_phys_addr;
920 hose->pci_io_size = size; 943 hose->pci_io_size = size;
@@ -948,7 +971,6 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
948 res->sibling = NULL; 971 res->sibling = NULL;
949 res->child = NULL; 972 res->child = NULL;
950 } 973 }
951 ranges += np;
952 } 974 }
953} 975}
954 976
diff --git a/arch/ppc64/kernel/rtas_pci.c b/arch/ppc64/kernel/rtas_pci.c
index 20361bcd8cfb..3ad15c90fbbd 100644
--- a/arch/ppc64/kernel/rtas_pci.c
+++ b/arch/ppc64/kernel/rtas_pci.c
@@ -400,7 +400,7 @@ unsigned long __init find_and_init_phbs(void)
400 if (!phb) 400 if (!phb)
401 continue; 401 continue;
402 402
403 pci_process_bridge_OF_ranges(phb, node); 403 pci_process_bridge_OF_ranges(phb, node, 0);
404 pci_setup_phb_io(phb, index == 0); 404 pci_setup_phb_io(phb, index == 0);
405#ifdef CONFIG_PPC_PSERIES 405#ifdef CONFIG_PPC_PSERIES
406 if (ppc64_interrupt_controller == IC_OPEN_PIC && pSeries_mpic) { 406 if (ppc64_interrupt_controller == IC_OPEN_PIC && pSeries_mpic) {
@@ -450,7 +450,7 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
450 if (!phb) 450 if (!phb)
451 return NULL; 451 return NULL;
452 452
453 pci_process_bridge_OF_ranges(phb, dn); 453 pci_process_bridge_OF_ranges(phb, dn, primary);
454 454
455 pci_setup_phb_io_dynamic(phb, primary); 455 pci_setup_phb_io_dynamic(phb, primary);
456 of_node_put(root); 456 of_node_put(root);
diff --git a/include/asm-ppc64/pci-bridge.h b/include/asm-ppc64/pci-bridge.h
index 7d8ecb507a3d..60cf8c838af0 100644
--- a/include/asm-ppc64/pci-bridge.h
+++ b/include/asm-ppc64/pci-bridge.h
@@ -123,7 +123,7 @@ static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
123} 123}
124 124
125extern void pci_process_bridge_OF_ranges(struct pci_controller *hose, 125extern void pci_process_bridge_OF_ranges(struct pci_controller *hose,
126 struct device_node *dev); 126 struct device_node *dev, int primary);
127 127
128extern int pcibios_remove_root_bus(struct pci_controller *phb); 128extern int pcibios_remove_root_bus(struct pci_controller *phb);
129 129