diff options
| -rw-r--r-- | drivers/pci/setup-bus.c | 114 |
1 files changed, 2 insertions, 112 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 4fe36d2e1049..19b111383f62 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
| @@ -838,65 +838,11 @@ static void pci_bus_dump_resources(struct pci_bus *bus) | |||
| 838 | } | 838 | } |
| 839 | } | 839 | } |
| 840 | 840 | ||
| 841 | static int __init pci_bus_get_depth(struct pci_bus *bus) | ||
| 842 | { | ||
| 843 | int depth = 0; | ||
| 844 | struct pci_dev *dev; | ||
| 845 | |||
| 846 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
| 847 | int ret; | ||
| 848 | struct pci_bus *b = dev->subordinate; | ||
| 849 | if (!b) | ||
| 850 | continue; | ||
| 851 | |||
| 852 | ret = pci_bus_get_depth(b); | ||
| 853 | if (ret + 1 > depth) | ||
| 854 | depth = ret + 1; | ||
| 855 | } | ||
| 856 | |||
| 857 | return depth; | ||
| 858 | } | ||
| 859 | static int __init pci_get_max_depth(void) | ||
| 860 | { | ||
| 861 | int depth = 0; | ||
| 862 | struct pci_bus *bus; | ||
| 863 | |||
| 864 | list_for_each_entry(bus, &pci_root_buses, node) { | ||
| 865 | int ret; | ||
| 866 | |||
| 867 | ret = pci_bus_get_depth(bus); | ||
| 868 | if (ret > depth) | ||
| 869 | depth = ret; | ||
| 870 | } | ||
| 871 | |||
| 872 | return depth; | ||
| 873 | } | ||
| 874 | |||
| 875 | /* | ||
| 876 | * first try will not touch pci bridge res | ||
| 877 | * second and later try will clear small leaf bridge res | ||
| 878 | * will stop till to the max deepth if can not find good one | ||
| 879 | */ | ||
| 880 | void __init | 841 | void __init |
| 881 | pci_assign_unassigned_resources(void) | 842 | pci_assign_unassigned_resources(void) |
| 882 | { | 843 | { |
| 883 | struct pci_bus *bus; | 844 | struct pci_bus *bus; |
| 884 | int tried_times = 0; | ||
| 885 | enum release_type rel_type = leaf_only; | ||
| 886 | struct resource_list_x head, *list; | ||
| 887 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | | ||
| 888 | IORESOURCE_PREFETCH; | ||
| 889 | unsigned long failed_type; | ||
| 890 | int max_depth = pci_get_max_depth(); | ||
| 891 | int pci_try_num; | ||
| 892 | 845 | ||
| 893 | head.next = NULL; | ||
| 894 | |||
| 895 | pci_try_num = max_depth + 1; | ||
| 896 | printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n", | ||
| 897 | max_depth, pci_try_num); | ||
| 898 | |||
| 899 | again: | ||
| 900 | /* Depth first, calculate sizes and alignments of all | 846 | /* Depth first, calculate sizes and alignments of all |
| 901 | subordinate buses. */ | 847 | subordinate buses. */ |
| 902 | list_for_each_entry(bus, &pci_root_buses, node) { | 848 | list_for_each_entry(bus, &pci_root_buses, node) { |
| @@ -904,65 +850,9 @@ again: | |||
| 904 | } | 850 | } |
| 905 | /* Depth last, allocate resources and update the hardware. */ | 851 | /* Depth last, allocate resources and update the hardware. */ |
| 906 | list_for_each_entry(bus, &pci_root_buses, node) { | 852 | list_for_each_entry(bus, &pci_root_buses, node) { |
| 907 | __pci_bus_assign_resources(bus, &head); | 853 | pci_bus_assign_resources(bus); |
| 908 | } | ||
| 909 | tried_times++; | ||
| 910 | |||
| 911 | /* any device complain? */ | ||
| 912 | if (!head.next) | ||
| 913 | goto enable_and_dump; | ||
| 914 | failed_type = 0; | ||
| 915 | for (list = head.next; list;) { | ||
| 916 | failed_type |= list->flags; | ||
| 917 | list = list->next; | ||
| 918 | } | ||
| 919 | /* | ||
| 920 | * io port are tight, don't try extra | ||
| 921 | * or if reach the limit, don't want to try more | ||
| 922 | */ | ||
| 923 | failed_type &= type_mask; | ||
| 924 | if ((failed_type == IORESOURCE_IO) || (tried_times >= pci_try_num)) { | ||
| 925 | free_failed_list(&head); | ||
| 926 | goto enable_and_dump; | ||
| 927 | } | ||
| 928 | |||
| 929 | printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n", | ||
| 930 | tried_times + 1); | ||
| 931 | |||
| 932 | /* third times and later will not check if it is leaf */ | ||
| 933 | if ((tried_times + 1) > 2) | ||
| 934 | rel_type = whole_subtree; | ||
| 935 | |||
| 936 | /* | ||
| 937 | * Try to release leaf bridge's resources that doesn't fit resource of | ||
| 938 | * child device under that bridge | ||
| 939 | */ | ||
| 940 | for (list = head.next; list;) { | ||
| 941 | bus = list->dev->bus; | ||
| 942 | pci_bus_release_bridge_resources(bus, list->flags & type_mask, | ||
| 943 | rel_type); | ||
| 944 | list = list->next; | ||
| 945 | } | ||
| 946 | /* restore size and flags */ | ||
| 947 | for (list = head.next; list;) { | ||
| 948 | struct resource *res = list->res; | ||
| 949 | |||
| 950 | res->start = list->start; | ||
| 951 | res->end = list->end; | ||
| 952 | res->flags = list->flags; | ||
| 953 | if (list->dev->subordinate) | ||
| 954 | res->flags = 0; | ||
| 955 | |||
| 956 | list = list->next; | ||
| 957 | } | ||
| 958 | free_failed_list(&head); | ||
| 959 | |||
| 960 | goto again; | ||
| 961 | |||
| 962 | enable_and_dump: | ||
| 963 | /* Depth last, update the hardware. */ | ||
| 964 | list_for_each_entry(bus, &pci_root_buses, node) | ||
| 965 | pci_enable_bridges(bus); | 854 | pci_enable_bridges(bus); |
| 855 | } | ||
| 966 | 856 | ||
| 967 | /* dump the resource on buses */ | 857 | /* dump the resource on buses */ |
| 968 | list_for_each_entry(bus, &pci_root_buses, node) { | 858 | list_for_each_entry(bus, &pci_root_buses, node) { |
