diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2007-12-19 22:54:44 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-12-20 00:18:06 -0500 |
commit | b9baa20b0a50947f2e86d7775c9dba87c0d946ef (patch) | |
tree | 21659df63935450730be4c2a61c1f54e40693aba /arch/powerpc/kernel/pci_32.c | |
parent | 0ec6b5c1028f29aed07bc7c32945990c5cd48c14 (diff) |
[POWERPC] pci32: Remove PowerMac P2P bridge IO hack
The 32 bits PowerPC PCI code has a hack for use by some PowerMacs
to try to re-open PCI<->PCI bridge IO resources that were closed
by the firmware. This is no longer necessary as the generic code
will now do that for us.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/pci_32.c')
-rw-r--r-- | arch/powerpc/kernel/pci_32.c | 215 |
1 files changed, 1 insertions, 214 deletions
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 1020d04b0a5a..dfb165802529 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c | |||
@@ -711,217 +711,6 @@ void pcibios_make_OF_bus_map(void) | |||
711 | } | 711 | } |
712 | #endif /* CONFIG_PPC_OF */ | 712 | #endif /* CONFIG_PPC_OF */ |
713 | 713 | ||
714 | #ifdef CONFIG_PPC_PMAC | ||
715 | /* | ||
716 | * This set of routines checks for PCI<->PCI bridges that have closed | ||
717 | * IO resources and have child devices. It tries to re-open an IO | ||
718 | * window on them. | ||
719 | * | ||
720 | * This is a _temporary_ fix to workaround a problem with Apple's OF | ||
721 | * closing IO windows on P2P bridges when the OF drivers of cards | ||
722 | * below this bridge don't claim any IO range (typically ATI or | ||
723 | * Adaptec). | ||
724 | * | ||
725 | * A more complete fix would be to use drivers/pci/setup-bus.c, which | ||
726 | * involves a working pcibios_fixup_pbus_ranges(), some more care about | ||
727 | * ordering when creating the host bus resources, and maybe a few more | ||
728 | * minor tweaks | ||
729 | */ | ||
730 | |||
731 | /* Initialize bridges with base/limit values we have collected */ | ||
732 | static void __init | ||
733 | do_update_p2p_io_resource(struct pci_bus *bus, int enable_vga) | ||
734 | { | ||
735 | struct pci_dev *bridge = bus->self; | ||
736 | struct pci_controller* hose = (struct pci_controller *)bridge->sysdata; | ||
737 | u32 l; | ||
738 | u16 w; | ||
739 | struct resource res; | ||
740 | |||
741 | if (bus->resource[0] == NULL) | ||
742 | return; | ||
743 | res = *(bus->resource[0]); | ||
744 | |||
745 | DBG("Remapping Bus %d, bridge: %s\n", bus->number, pci_name(bridge)); | ||
746 | res.start -= ((unsigned long) hose->io_base_virt - isa_io_base); | ||
747 | res.end -= ((unsigned long) hose->io_base_virt - isa_io_base); | ||
748 | DBG(" IO window: %016llx-%016llx\n", res.start, res.end); | ||
749 | |||
750 | /* Set up the top and bottom of the PCI I/O segment for this bus. */ | ||
751 | pci_read_config_dword(bridge, PCI_IO_BASE, &l); | ||
752 | l &= 0xffff000f; | ||
753 | l |= (res.start >> 8) & 0x00f0; | ||
754 | l |= res.end & 0xf000; | ||
755 | pci_write_config_dword(bridge, PCI_IO_BASE, l); | ||
756 | |||
757 | if ((l & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) { | ||
758 | l = (res.start >> 16) | (res.end & 0xffff0000); | ||
759 | pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, l); | ||
760 | } | ||
761 | |||
762 | pci_read_config_word(bridge, PCI_COMMAND, &w); | ||
763 | w |= PCI_COMMAND_IO; | ||
764 | pci_write_config_word(bridge, PCI_COMMAND, w); | ||
765 | |||
766 | #if 0 /* Enabling this causes XFree 4.2.0 to hang during PCI probe */ | ||
767 | if (enable_vga) { | ||
768 | pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &w); | ||
769 | w |= PCI_BRIDGE_CTL_VGA; | ||
770 | pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, w); | ||
771 | } | ||
772 | #endif | ||
773 | } | ||
774 | |||
775 | /* This function is pretty basic and actually quite broken for the | ||
776 | * general case, it's enough for us right now though. It's supposed | ||
777 | * to tell us if we need to open an IO range at all or not and what | ||
778 | * size. | ||
779 | */ | ||
780 | static int __init | ||
781 | check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga) | ||
782 | { | ||
783 | struct pci_dev *dev; | ||
784 | int i; | ||
785 | int rc = 0; | ||
786 | |||
787 | #define push_end(res, mask) do { \ | ||
788 | BUG_ON((mask+1) & mask); \ | ||
789 | res->end = (res->end + mask) | mask; \ | ||
790 | } while (0) | ||
791 | |||
792 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
793 | u16 class = dev->class >> 8; | ||
794 | |||
795 | if (class == PCI_CLASS_DISPLAY_VGA || | ||
796 | class == PCI_CLASS_NOT_DEFINED_VGA) | ||
797 | *found_vga = 1; | ||
798 | if (class >> 8 == PCI_BASE_CLASS_BRIDGE && dev->subordinate) | ||
799 | rc |= check_for_io_childs(dev->subordinate, res, found_vga); | ||
800 | if (class == PCI_CLASS_BRIDGE_CARDBUS) | ||
801 | push_end(res, 0xfff); | ||
802 | |||
803 | for (i=0; i<PCI_NUM_RESOURCES; i++) { | ||
804 | struct resource *r; | ||
805 | unsigned long r_size; | ||
806 | |||
807 | if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI | ||
808 | && i >= PCI_BRIDGE_RESOURCES) | ||
809 | continue; | ||
810 | r = &dev->resource[i]; | ||
811 | r_size = r->end - r->start; | ||
812 | if (r_size < 0xfff) | ||
813 | r_size = 0xfff; | ||
814 | if (r->flags & IORESOURCE_IO && (r_size) != 0) { | ||
815 | rc = 1; | ||
816 | push_end(res, r_size); | ||
817 | } | ||
818 | } | ||
819 | } | ||
820 | |||
821 | return rc; | ||
822 | } | ||
823 | |||
824 | /* Here we scan all P2P bridges of a given level that have a closed | ||
825 | * IO window. Note that the test for the presence of a VGA card should | ||
826 | * be improved to take into account already configured P2P bridges, | ||
827 | * currently, we don't see them and might end up configuring 2 bridges | ||
828 | * with VGA pass through enabled | ||
829 | */ | ||
830 | static void __init | ||
831 | do_fixup_p2p_level(struct pci_bus *bus) | ||
832 | { | ||
833 | struct pci_bus *b; | ||
834 | int i, parent_io; | ||
835 | int has_vga = 0; | ||
836 | |||
837 | for (parent_io=0; parent_io<4; parent_io++) | ||
838 | if (bus->resource[parent_io] | ||
839 | && bus->resource[parent_io]->flags & IORESOURCE_IO) | ||
840 | break; | ||
841 | if (parent_io >= 4) | ||
842 | return; | ||
843 | |||
844 | list_for_each_entry(b, &bus->children, node) { | ||
845 | struct pci_dev *d = b->self; | ||
846 | struct pci_controller* hose = (struct pci_controller *)d->sysdata; | ||
847 | struct resource *res = b->resource[0]; | ||
848 | struct resource tmp_res; | ||
849 | unsigned long max; | ||
850 | int found_vga = 0; | ||
851 | |||
852 | memset(&tmp_res, 0, sizeof(tmp_res)); | ||
853 | tmp_res.start = bus->resource[parent_io]->start; | ||
854 | |||
855 | /* We don't let low addresses go through that closed P2P bridge, well, | ||
856 | * that may not be necessary but I feel safer that way | ||
857 | */ | ||
858 | if (tmp_res.start == 0) | ||
859 | tmp_res.start = 0x1000; | ||
860 | |||
861 | if (!list_empty(&b->devices) && res && res->flags == 0 && | ||
862 | res != bus->resource[parent_io] && | ||
863 | (d->class >> 8) == PCI_CLASS_BRIDGE_PCI && | ||
864 | check_for_io_childs(b, &tmp_res, &found_vga)) { | ||
865 | u8 io_base_lo; | ||
866 | |||
867 | printk(KERN_INFO "Fixing up IO bus %s\n", b->name); | ||
868 | |||
869 | if (found_vga) { | ||
870 | if (has_vga) { | ||
871 | printk(KERN_WARNING "Skipping VGA, already active" | ||
872 | " on bus segment\n"); | ||
873 | found_vga = 0; | ||
874 | } else | ||
875 | has_vga = 1; | ||
876 | } | ||
877 | pci_read_config_byte(d, PCI_IO_BASE, &io_base_lo); | ||
878 | |||
879 | if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) | ||
880 | max = ((unsigned long) hose->io_base_virt | ||
881 | - isa_io_base) + 0xffffffff; | ||
882 | else | ||
883 | max = ((unsigned long) hose->io_base_virt | ||
884 | - isa_io_base) + 0xffff; | ||
885 | |||
886 | *res = tmp_res; | ||
887 | res->flags = IORESOURCE_IO; | ||
888 | res->name = b->name; | ||
889 | |||
890 | /* Find a resource in the parent where we can allocate */ | ||
891 | for (i = 0 ; i < 4; i++) { | ||
892 | struct resource *r = bus->resource[i]; | ||
893 | if (!r) | ||
894 | continue; | ||
895 | if ((r->flags & IORESOURCE_IO) == 0) | ||
896 | continue; | ||
897 | DBG("Trying to allocate from %016llx, size %016llx from parent" | ||
898 | " res %d: %016llx -> %016llx\n", | ||
899 | res->start, res->end, i, r->start, r->end); | ||
900 | |||
901 | if (allocate_resource(r, res, res->end + 1, res->start, max, | ||
902 | res->end + 1, NULL, NULL) < 0) { | ||
903 | DBG("Failed !\n"); | ||
904 | continue; | ||
905 | } | ||
906 | do_update_p2p_io_resource(b, found_vga); | ||
907 | break; | ||
908 | } | ||
909 | } | ||
910 | do_fixup_p2p_level(b); | ||
911 | } | ||
912 | } | ||
913 | |||
914 | static void | ||
915 | pcibios_fixup_p2p_bridges(void) | ||
916 | { | ||
917 | struct pci_bus *b; | ||
918 | |||
919 | list_for_each_entry(b, &pci_root_buses, node) | ||
920 | do_fixup_p2p_level(b); | ||
921 | } | ||
922 | |||
923 | #endif /* CONFIG_PPC_PMAC */ | ||
924 | |||
925 | static int __init | 714 | static int __init |
926 | pcibios_init(void) | 715 | pcibios_init(void) |
927 | { | 716 | { |
@@ -961,9 +750,7 @@ pcibios_init(void) | |||
961 | pcibios_allocate_bus_resources(&pci_root_buses); | 750 | pcibios_allocate_bus_resources(&pci_root_buses); |
962 | pcibios_allocate_resources(0); | 751 | pcibios_allocate_resources(0); |
963 | pcibios_allocate_resources(1); | 752 | pcibios_allocate_resources(1); |
964 | #ifdef CONFIG_PPC_PMAC | 753 | |
965 | pcibios_fixup_p2p_bridges(); | ||
966 | #endif /* CONFIG_PPC_PMAC */ | ||
967 | DBG("PCI: Assigning unassigned resouces...\n"); | 754 | DBG("PCI: Assigning unassigned resouces...\n"); |
968 | pci_assign_unassigned_resources(); | 755 | pci_assign_unassigned_resources(); |
969 | 756 | ||