aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/setup-bus.c125
1 files changed, 117 insertions, 8 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index ebf51ad1b714..7a65db400253 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -991,30 +991,139 @@ static void pci_bus_dump_resources(struct pci_bus *bus)
991 } 991 }
992} 992}
993 993
994static int __init pci_bus_get_depth(struct pci_bus *bus)
995{
996 int depth = 0;
997 struct pci_dev *dev;
998
999 list_for_each_entry(dev, &bus->devices, bus_list) {
1000 int ret;
1001 struct pci_bus *b = dev->subordinate;
1002 if (!b)
1003 continue;
1004
1005 ret = pci_bus_get_depth(b);
1006 if (ret + 1 > depth)
1007 depth = ret + 1;
1008 }
1009
1010 return depth;
1011}
1012static int __init pci_get_max_depth(void)
1013{
1014 int depth = 0;
1015 struct pci_bus *bus;
1016
1017 list_for_each_entry(bus, &pci_root_buses, node) {
1018 int ret;
1019
1020 ret = pci_bus_get_depth(bus);
1021 if (ret > depth)
1022 depth = ret;
1023 }
1024
1025 return depth;
1026}
1027
1028/*
1029 * first try will not touch pci bridge res
1030 * second and later try will clear small leaf bridge res
1031 * will stop till to the max deepth if can not find good one
1032 */
994void __init 1033void __init
995pci_assign_unassigned_resources(void) 1034pci_assign_unassigned_resources(void)
996{ 1035{
997 struct pci_bus *bus; 1036 struct pci_bus *bus;
998 struct resource_list_x add_list; /* list of resources that 1037 struct resource_list_x add_list; /* list of resources that
999 want additional resources */ 1038 want additional resources */
1039 int tried_times = 0;
1040 enum release_type rel_type = leaf_only;
1041 struct resource_list_x head, *list;
1042 unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
1043 IORESOURCE_PREFETCH;
1044 unsigned long failed_type;
1045 int max_depth = pci_get_max_depth();
1046 int pci_try_num;
1047
1048
1049 head.next = NULL;
1000 add_list.next = NULL; 1050 add_list.next = NULL;
1051
1052 pci_try_num = max_depth + 1;
1053 printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n",
1054 max_depth, pci_try_num);
1055
1056again:
1001 /* Depth first, calculate sizes and alignments of all 1057 /* Depth first, calculate sizes and alignments of all
1002 subordinate buses. */ 1058 subordinate buses. */
1003 list_for_each_entry(bus, &pci_root_buses, node) { 1059 list_for_each_entry(bus, &pci_root_buses, node)
1004 __pci_bus_size_bridges(bus, &add_list); 1060 __pci_bus_size_bridges(bus, &add_list);
1005 }
1006 1061
1007 /* Depth last, allocate resources and update the hardware. */ 1062 /* Depth last, allocate resources and update the hardware. */
1008 list_for_each_entry(bus, &pci_root_buses, node) { 1063 list_for_each_entry(bus, &pci_root_buses, node)
1009 __pci_bus_assign_resources(bus, &add_list, NULL); 1064 __pci_bus_assign_resources(bus, &add_list, &head);
1010 pci_enable_bridges(bus);
1011 }
1012 BUG_ON(add_list.next); 1065 BUG_ON(add_list.next);
1066 tried_times++;
1067
1068 /* any device complain? */
1069 if (!head.next)
1070 goto enable_and_dump;
1071 failed_type = 0;
1072 for (list = head.next; list;) {
1073 failed_type |= list->flags;
1074 list = list->next;
1075 }
1076 /*
1077 * io port are tight, don't try extra
1078 * or if reach the limit, don't want to try more
1079 */
1080 failed_type &= type_mask;
1081 if ((failed_type == IORESOURCE_IO) || (tried_times >= pci_try_num)) {
1082 free_list(resource_list_x, &head);
1083 goto enable_and_dump;
1084 }
1085
1086 printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n",
1087 tried_times + 1);
1088
1089 /* third times and later will not check if it is leaf */
1090 if ((tried_times + 1) > 2)
1091 rel_type = whole_subtree;
1092
1093 /*
1094 * Try to release leaf bridge's resources that doesn't fit resource of
1095 * child device under that bridge
1096 */
1097 for (list = head.next; list;) {
1098 bus = list->dev->bus;
1099 pci_bus_release_bridge_resources(bus, list->flags & type_mask,
1100 rel_type);
1101 list = list->next;
1102 }
1103 /* restore size and flags */
1104 for (list = head.next; list;) {
1105 struct resource *res = list->res;
1106
1107 res->start = list->start;
1108 res->end = list->end;
1109 res->flags = list->flags;
1110 if (list->dev->subordinate)
1111 res->flags = 0;
1112
1113 list = list->next;
1114 }
1115 free_list(resource_list_x, &head);
1116
1117 goto again;
1118
1119enable_and_dump:
1120 /* Depth last, update the hardware. */
1121 list_for_each_entry(bus, &pci_root_buses, node)
1122 pci_enable_bridges(bus);
1013 1123
1014 /* dump the resource on buses */ 1124 /* dump the resource on buses */
1015 list_for_each_entry(bus, &pci_root_buses, node) { 1125 list_for_each_entry(bus, &pci_root_buses, node)
1016 pci_bus_dump_resources(bus); 1126 pci_bus_dump_resources(bus);
1017 }
1018} 1127}
1019 1128
1020void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) 1129void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)