aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64/kernel/pci.c
diff options
context:
space:
mode:
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,
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