diff options
| -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); |
