diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/kernel/pci-common.c | 163 |
1 files changed, 116 insertions, 47 deletions
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 8c0270929cc0..01ce8c38bae6 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
@@ -780,11 +780,6 @@ static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) | |||
780 | 780 | ||
781 | res->start = (res->start + offset) & mask; | 781 | res->start = (res->start + offset) & mask; |
782 | res->end = (res->end + offset) & mask; | 782 | res->end = (res->end + offset) & mask; |
783 | |||
784 | pr_debug("PCI:%s %016llx-%016llx\n", | ||
785 | pci_name(dev), | ||
786 | (unsigned long long)res->start, | ||
787 | (unsigned long long)res->end); | ||
788 | } | 783 | } |
789 | 784 | ||
790 | 785 | ||
@@ -830,6 +825,11 @@ static void __devinit pcibios_fixup_resources(struct pci_dev *dev) | |||
830 | (unsigned int)res->flags); | 825 | (unsigned int)res->flags); |
831 | 826 | ||
832 | fixup_resource(res, dev); | 827 | fixup_resource(res, dev); |
828 | |||
829 | pr_debug("PCI:%s %016llx-%016llx\n", | ||
830 | pci_name(dev), | ||
831 | (unsigned long long)res->start, | ||
832 | (unsigned long long)res->end); | ||
833 | } | 833 | } |
834 | 834 | ||
835 | /* Call machine specific resource fixup */ | 835 | /* Call machine specific resource fixup */ |
@@ -838,58 +838,127 @@ static void __devinit pcibios_fixup_resources(struct pci_dev *dev) | |||
838 | } | 838 | } |
839 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources); | 839 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources); |
840 | 840 | ||
841 | static void __devinit __pcibios_fixup_bus(struct pci_bus *bus) | 841 | /* This function tries to figure out if a bridge resource has been initialized |
842 | * by the firmware or not. It doesn't have to be absolutely bullet proof, but | ||
843 | * things go more smoothly when it gets it right. It should covers cases such | ||
844 | * as Apple "closed" bridge resources and bare-metal pSeries unassigned bridges | ||
845 | */ | ||
846 | static int __devinit pcibios_uninitialized_bridge_resource(struct pci_bus *bus, | ||
847 | struct resource *res) | ||
842 | { | 848 | { |
843 | struct pci_controller *hose = pci_bus_to_host(bus); | 849 | struct pci_controller *hose = pci_bus_to_host(bus); |
844 | struct pci_dev *dev = bus->self; | 850 | struct pci_dev *dev = bus->self; |
851 | resource_size_t offset; | ||
852 | u16 command; | ||
853 | int i; | ||
845 | 854 | ||
846 | pr_debug("PCI: Fixup bus %d (%s)\n", bus->number, dev ? pci_name(dev) : "PHB"); | 855 | /* We don't do anything if PCI_PROBE_ONLY is set */ |
856 | if (ppc_pci_flags & PPC_PCI_PROBE_ONLY) | ||
857 | return 0; | ||
847 | 858 | ||
848 | /* Fixup PCI<->PCI bridges. Host bridges are handled separately, for | 859 | /* Job is a bit different between memory and IO */ |
849 | * now differently between 32 and 64 bits. | 860 | if (res->flags & IORESOURCE_MEM) { |
850 | */ | 861 | /* If the BAR is non-0 (res != pci_mem_offset) then it's probably been |
851 | if (dev != NULL) { | 862 | * initialized by somebody |
852 | struct resource *res; | 863 | */ |
853 | int i; | 864 | if (res->start != hose->pci_mem_offset) |
865 | return 0; | ||
854 | 866 | ||
855 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) { | 867 | /* The BAR is 0, let's check if memory decoding is enabled on |
856 | if ((res = bus->resource[i]) == NULL) | 868 | * the bridge. If not, we consider it unassigned |
857 | continue; | 869 | */ |
858 | if (!res->flags) | 870 | pci_read_config_word(dev, PCI_COMMAND, &command); |
859 | continue; | 871 | if ((command & PCI_COMMAND_MEMORY) == 0) |
860 | if (i >= 3 && bus->self->transparent) | 872 | return 1; |
861 | continue; | ||
862 | /* On PowerMac, Apple leaves bridge windows open over | ||
863 | * an inaccessible region of memory space (0...fffff) | ||
864 | * which is somewhat bogus, but that's what they think | ||
865 | * means disabled... | ||
866 | * | ||
867 | * We clear those to force them to be reallocated later | ||
868 | * | ||
869 | * We detect such regions by the fact that the base is | ||
870 | * equal to the pci_mem_offset of the host bridge and | ||
871 | * their size is smaller than 1M. | ||
872 | */ | ||
873 | if (res->flags & IORESOURCE_MEM && | ||
874 | res->start == hose->pci_mem_offset && | ||
875 | res->end < 0x100000) { | ||
876 | printk(KERN_INFO | ||
877 | "PCI: Closing bogus Apple Firmware" | ||
878 | " region %d on bus 0x%02x\n", | ||
879 | i, bus->number); | ||
880 | res->flags = 0; | ||
881 | continue; | ||
882 | } | ||
883 | 873 | ||
884 | pr_debug("PCI:%s Bus rsrc %d %016llx-%016llx [%x] fixup...\n", | 874 | /* Memory decoding is enabled and the BAR is 0. If any of the bridge |
885 | pci_name(dev), i, | 875 | * resources covers that starting address (0 then it's good enough for |
886 | (unsigned long long)res->start,\ | 876 | * us for memory |
887 | (unsigned long long)res->end, | 877 | */ |
888 | (unsigned int)res->flags); | 878 | for (i = 0; i < 3; i++) { |
879 | if ((hose->mem_resources[i].flags & IORESOURCE_MEM) && | ||
880 | hose->mem_resources[i].start == hose->pci_mem_offset) | ||
881 | return 0; | ||
882 | } | ||
883 | |||
884 | /* Well, it starts at 0 and we know it will collide so we may as | ||
885 | * well consider it as unassigned. That covers the Apple case. | ||
886 | */ | ||
887 | return 1; | ||
888 | } else { | ||
889 | /* If the BAR is non-0, then we consider it assigned */ | ||
890 | offset = (unsigned long)hose->io_base_virt - _IO_BASE; | ||
891 | if (((res->start - offset) & 0xfffffffful) != 0) | ||
892 | return 0; | ||
893 | |||
894 | /* Here, we are a bit different than memory as typically IO space | ||
895 | * starting at low addresses -is- valid. What we do instead if that | ||
896 | * we consider as unassigned anything that doesn't have IO enabled | ||
897 | * in the PCI command register, and that's it. | ||
898 | */ | ||
899 | pci_read_config_word(dev, PCI_COMMAND, &command); | ||
900 | if (command & PCI_COMMAND_IO) | ||
901 | return 0; | ||
902 | |||
903 | /* It's starting at 0 and IO is disabled in the bridge, consider | ||
904 | * it unassigned | ||
905 | */ | ||
906 | return 1; | ||
907 | } | ||
908 | } | ||
909 | |||
910 | /* Fixup resources of a PCI<->PCI bridge */ | ||
911 | static void __devinit pcibios_fixup_bridge(struct pci_bus *bus) | ||
912 | { | ||
913 | struct resource *res; | ||
914 | int i; | ||
915 | |||
916 | struct pci_dev *dev = bus->self; | ||
889 | 917 | ||
890 | fixup_resource(res, dev); | 918 | for (i = 0; i < PCI_BUS_NUM_RESOURCES; ++i) { |
919 | if ((res = bus->resource[i]) == NULL) | ||
920 | continue; | ||
921 | if (!res->flags) | ||
922 | continue; | ||
923 | if (i >= 3 && bus->self->transparent) | ||
924 | continue; | ||
925 | |||
926 | pr_debug("PCI:%s Bus rsrc %d %016llx-%016llx [%x] fixup...\n", | ||
927 | pci_name(dev), i, | ||
928 | (unsigned long long)res->start,\ | ||
929 | (unsigned long long)res->end, | ||
930 | (unsigned int)res->flags); | ||
931 | |||
932 | /* Perform fixup */ | ||
933 | fixup_resource(res, dev); | ||
934 | |||
935 | /* Try to detect uninitialized P2P bridge resources, | ||
936 | * and clear them out so they get re-assigned later | ||
937 | */ | ||
938 | if (pcibios_uninitialized_bridge_resource(bus, res)) { | ||
939 | res->flags = 0; | ||
940 | pr_debug("PCI:%s (unassigned)\n", pci_name(dev)); | ||
941 | } else { | ||
942 | |||
943 | pr_debug("PCI:%s %016llx-%016llx\n", | ||
944 | pci_name(dev), | ||
945 | (unsigned long long)res->start, | ||
946 | (unsigned long long)res->end); | ||
891 | } | 947 | } |
892 | } | 948 | } |
949 | } | ||
950 | |||
951 | static void __devinit __pcibios_fixup_bus(struct pci_bus *bus) | ||
952 | { | ||
953 | struct pci_dev *dev = bus->self; | ||
954 | |||
955 | pr_debug("PCI: Fixup bus %d (%s)\n", bus->number, dev ? pci_name(dev) : "PHB"); | ||
956 | |||
957 | /* Fixup PCI<->PCI bridges. Host bridges are handled separately, for | ||
958 | * now differently between 32 and 64 bits. | ||
959 | */ | ||
960 | if (dev != NULL) | ||
961 | pcibios_fixup_bridge(bus); | ||
893 | 962 | ||
894 | /* Additional setup that is different between 32 and 64 bits for now */ | 963 | /* Additional setup that is different between 32 and 64 bits for now */ |
895 | pcibios_do_bus_setup(bus); | 964 | pcibios_do_bus_setup(bus); |