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