diff options
-rw-r--r-- | arch/ppc64/kernel/maple_pci.c | 2 | ||||
-rw-r--r-- | arch/ppc64/kernel/pci.c | 38 | ||||
-rw-r--r-- | arch/ppc64/kernel/rtas_pci.c | 4 | ||||
-rw-r--r-- | include/asm-ppc64/pci-bridge.h | 2 |
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 | ||
882 | void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose, | 882 | void __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 | ||
125 | extern void pci_process_bridge_OF_ranges(struct pci_controller *hose, | 125 | extern void pci_process_bridge_OF_ranges(struct pci_controller *hose, |
126 | struct device_node *dev); | 126 | struct device_node *dev, int primary); |
127 | 127 | ||
128 | extern int pcibios_remove_root_bus(struct pci_controller *phb); | 128 | extern int pcibios_remove_root_bus(struct pci_controller *phb); |
129 | 129 | ||