diff options
Diffstat (limited to 'drivers/pci/setup-bus.c')
-rw-r--r-- | drivers/pci/setup-bus.c | 222 |
1 files changed, 155 insertions, 67 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index d219d44709b2..d9fdcea4412a 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
@@ -713,12 +713,11 @@ static void pci_bridge_check_ranges(struct pci_bus *bus) | |||
713 | bus resource of a given type. Note: we intentionally skip | 713 | bus resource of a given type. Note: we intentionally skip |
714 | the bus resources which have already been assigned (that is, | 714 | the bus resources which have already been assigned (that is, |
715 | have non-NULL parent resource). */ | 715 | have non-NULL parent resource). */ |
716 | static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned long type) | 716 | static struct resource *find_free_bus_resource(struct pci_bus *bus, |
717 | unsigned long type_mask, unsigned long type) | ||
717 | { | 718 | { |
718 | int i; | 719 | int i; |
719 | struct resource *r; | 720 | struct resource *r; |
720 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | | ||
721 | IORESOURCE_PREFETCH; | ||
722 | 721 | ||
723 | pci_bus_for_each_resource(bus, r, i) { | 722 | pci_bus_for_each_resource(bus, r, i) { |
724 | if (r == &ioport_resource || r == &iomem_resource) | 723 | if (r == &ioport_resource || r == &iomem_resource) |
@@ -815,7 +814,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, | |||
815 | resource_size_t add_size, struct list_head *realloc_head) | 814 | resource_size_t add_size, struct list_head *realloc_head) |
816 | { | 815 | { |
817 | struct pci_dev *dev; | 816 | struct pci_dev *dev; |
818 | struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); | 817 | struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO, |
818 | IORESOURCE_IO); | ||
819 | resource_size_t size = 0, size0 = 0, size1 = 0; | 819 | resource_size_t size = 0, size0 = 0, size1 = 0; |
820 | resource_size_t children_add_size = 0; | 820 | resource_size_t children_add_size = 0; |
821 | resource_size_t min_align, align; | 821 | resource_size_t min_align, align; |
@@ -907,36 +907,40 @@ static inline resource_size_t calculate_mem_align(resource_size_t *aligns, | |||
907 | * @bus : the bus | 907 | * @bus : the bus |
908 | * @mask: mask the resource flag, then compare it with type | 908 | * @mask: mask the resource flag, then compare it with type |
909 | * @type: the type of free resource from bridge | 909 | * @type: the type of free resource from bridge |
910 | * @type2: second match type | ||
911 | * @type3: third match type | ||
910 | * @min_size : the minimum memory window that must to be allocated | 912 | * @min_size : the minimum memory window that must to be allocated |
911 | * @add_size : additional optional memory window | 913 | * @add_size : additional optional memory window |
912 | * @realloc_head : track the additional memory window on this list | 914 | * @realloc_head : track the additional memory window on this list |
913 | * | 915 | * |
914 | * Calculate the size of the bus and minimal alignment which | 916 | * Calculate the size of the bus and minimal alignment which |
915 | * guarantees that all child resources fit in this size. | 917 | * guarantees that all child resources fit in this size. |
918 | * | ||
919 | * Returns -ENOSPC if there's no available bus resource of the desired type. | ||
920 | * Otherwise, sets the bus resource start/end to indicate the required | ||
921 | * size, adds things to realloc_head (if supplied), and returns 0. | ||
916 | */ | 922 | */ |
917 | static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | 923 | static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, |
918 | unsigned long type, resource_size_t min_size, | 924 | unsigned long type, unsigned long type2, |
919 | resource_size_t add_size, | 925 | unsigned long type3, |
920 | struct list_head *realloc_head) | 926 | resource_size_t min_size, resource_size_t add_size, |
927 | struct list_head *realloc_head) | ||
921 | { | 928 | { |
922 | struct pci_dev *dev; | 929 | struct pci_dev *dev; |
923 | resource_size_t min_align, align, size, size0, size1; | 930 | resource_size_t min_align, align, size, size0, size1; |
924 | resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */ | 931 | resource_size_t aligns[14]; /* Alignments from 1Mb to 8Gb */ |
925 | int order, max_order; | 932 | int order, max_order; |
926 | struct resource *b_res = find_free_bus_resource(bus, type); | 933 | struct resource *b_res = find_free_bus_resource(bus, |
927 | unsigned int mem64_mask = 0; | 934 | mask | IORESOURCE_PREFETCH, type); |
928 | resource_size_t children_add_size = 0; | 935 | resource_size_t children_add_size = 0; |
929 | 936 | ||
930 | if (!b_res) | 937 | if (!b_res) |
931 | return 0; | 938 | return -ENOSPC; |
932 | 939 | ||
933 | memset(aligns, 0, sizeof(aligns)); | 940 | memset(aligns, 0, sizeof(aligns)); |
934 | max_order = 0; | 941 | max_order = 0; |
935 | size = 0; | 942 | size = 0; |
936 | 943 | ||
937 | mem64_mask = b_res->flags & IORESOURCE_MEM_64; | ||
938 | b_res->flags &= ~IORESOURCE_MEM_64; | ||
939 | |||
940 | list_for_each_entry(dev, &bus->devices, bus_list) { | 944 | list_for_each_entry(dev, &bus->devices, bus_list) { |
941 | int i; | 945 | int i; |
942 | 946 | ||
@@ -944,7 +948,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
944 | struct resource *r = &dev->resource[i]; | 948 | struct resource *r = &dev->resource[i]; |
945 | resource_size_t r_size; | 949 | resource_size_t r_size; |
946 | 950 | ||
947 | if (r->parent || (r->flags & mask) != type) | 951 | if (r->parent || ((r->flags & mask) != type && |
952 | (r->flags & mask) != type2 && | ||
953 | (r->flags & mask) != type3)) | ||
948 | continue; | 954 | continue; |
949 | r_size = resource_size(r); | 955 | r_size = resource_size(r); |
950 | #ifdef CONFIG_PCI_IOV | 956 | #ifdef CONFIG_PCI_IOV |
@@ -957,10 +963,17 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
957 | continue; | 963 | continue; |
958 | } | 964 | } |
959 | #endif | 965 | #endif |
960 | /* For bridges size != alignment */ | 966 | /* |
967 | * aligns[0] is for 1MB (since bridge memory | ||
968 | * windows are always at least 1MB aligned), so | ||
969 | * keep "order" from being negative for smaller | ||
970 | * resources. | ||
971 | */ | ||
961 | align = pci_resource_alignment(dev, r); | 972 | align = pci_resource_alignment(dev, r); |
962 | order = __ffs(align) - 20; | 973 | order = __ffs(align) - 20; |
963 | if (order > 11) { | 974 | if (order < 0) |
975 | order = 0; | ||
976 | if (order >= ARRAY_SIZE(aligns)) { | ||
964 | dev_warn(&dev->dev, "disabling BAR %d: %pR " | 977 | dev_warn(&dev->dev, "disabling BAR %d: %pR " |
965 | "(bad alignment %#llx)\n", i, r, | 978 | "(bad alignment %#llx)\n", i, r, |
966 | (unsigned long long) align); | 979 | (unsigned long long) align); |
@@ -968,15 +981,12 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
968 | continue; | 981 | continue; |
969 | } | 982 | } |
970 | size += r_size; | 983 | size += r_size; |
971 | if (order < 0) | ||
972 | order = 0; | ||
973 | /* Exclude ranges with size > align from | 984 | /* Exclude ranges with size > align from |
974 | calculation of the alignment. */ | 985 | calculation of the alignment. */ |
975 | if (r_size == align) | 986 | if (r_size == align) |
976 | aligns[order] += align; | 987 | aligns[order] += align; |
977 | if (order > max_order) | 988 | if (order > max_order) |
978 | max_order = order; | 989 | max_order = order; |
979 | mem64_mask &= r->flags & IORESOURCE_MEM_64; | ||
980 | 990 | ||
981 | if (realloc_head) | 991 | if (realloc_head) |
982 | children_add_size += get_res_add_size(realloc_head, r); | 992 | children_add_size += get_res_add_size(realloc_head, r); |
@@ -997,18 +1007,18 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, | |||
997 | "%pR to %pR (unused)\n", b_res, | 1007 | "%pR to %pR (unused)\n", b_res, |
998 | &bus->busn_res); | 1008 | &bus->busn_res); |
999 | b_res->flags = 0; | 1009 | b_res->flags = 0; |
1000 | return 1; | 1010 | return 0; |
1001 | } | 1011 | } |
1002 | b_res->start = min_align; | 1012 | b_res->start = min_align; |
1003 | b_res->end = size0 + min_align - 1; | 1013 | b_res->end = size0 + min_align - 1; |
1004 | b_res->flags |= IORESOURCE_STARTALIGN | mem64_mask; | 1014 | b_res->flags |= IORESOURCE_STARTALIGN; |
1005 | if (size1 > size0 && realloc_head) { | 1015 | if (size1 > size0 && realloc_head) { |
1006 | add_to_list(realloc_head, bus->self, b_res, size1-size0, min_align); | 1016 | add_to_list(realloc_head, bus->self, b_res, size1-size0, min_align); |
1007 | dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window " | 1017 | dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window " |
1008 | "%pR to %pR add_size %llx\n", b_res, | 1018 | "%pR to %pR add_size %llx\n", b_res, |
1009 | &bus->busn_res, (unsigned long long)size1-size0); | 1019 | &bus->busn_res, (unsigned long long)size1-size0); |
1010 | } | 1020 | } |
1011 | return 1; | 1021 | return 0; |
1012 | } | 1022 | } |
1013 | 1023 | ||
1014 | unsigned long pci_cardbus_resource_alignment(struct resource *res) | 1024 | unsigned long pci_cardbus_resource_alignment(struct resource *res) |
@@ -1116,8 +1126,10 @@ handle_done: | |||
1116 | void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head) | 1126 | void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head) |
1117 | { | 1127 | { |
1118 | struct pci_dev *dev; | 1128 | struct pci_dev *dev; |
1119 | unsigned long mask, prefmask; | 1129 | unsigned long mask, prefmask, type2 = 0, type3 = 0; |
1120 | resource_size_t additional_mem_size = 0, additional_io_size = 0; | 1130 | resource_size_t additional_mem_size = 0, additional_io_size = 0; |
1131 | struct resource *b_res; | ||
1132 | int ret; | ||
1121 | 1133 | ||
1122 | list_for_each_entry(dev, &bus->devices, bus_list) { | 1134 | list_for_each_entry(dev, &bus->devices, bus_list) { |
1123 | struct pci_bus *b = dev->subordinate; | 1135 | struct pci_bus *b = dev->subordinate; |
@@ -1151,26 +1163,78 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head) | |||
1151 | additional_io_size = pci_hotplug_io_size; | 1163 | additional_io_size = pci_hotplug_io_size; |
1152 | additional_mem_size = pci_hotplug_mem_size; | 1164 | additional_mem_size = pci_hotplug_mem_size; |
1153 | } | 1165 | } |
1154 | /* | 1166 | /* Fall through */ |
1155 | * Follow thru | ||
1156 | */ | ||
1157 | default: | 1167 | default: |
1158 | pbus_size_io(bus, realloc_head ? 0 : additional_io_size, | 1168 | pbus_size_io(bus, realloc_head ? 0 : additional_io_size, |
1159 | additional_io_size, realloc_head); | 1169 | additional_io_size, realloc_head); |
1160 | /* If the bridge supports prefetchable range, size it | 1170 | |
1161 | separately. If it doesn't, or its prefetchable window | 1171 | /* |
1162 | has already been allocated by arch code, try | 1172 | * If there's a 64-bit prefetchable MMIO window, compute |
1163 | non-prefetchable range for both types of PCI memory | 1173 | * the size required to put all 64-bit prefetchable |
1164 | resources. */ | 1174 | * resources in it. |
1175 | */ | ||
1176 | b_res = &bus->self->resource[PCI_BRIDGE_RESOURCES]; | ||
1165 | mask = IORESOURCE_MEM; | 1177 | mask = IORESOURCE_MEM; |
1166 | prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH; | 1178 | prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH; |
1167 | if (pbus_size_mem(bus, prefmask, prefmask, | 1179 | if (b_res[2].flags & IORESOURCE_MEM_64) { |
1180 | prefmask |= IORESOURCE_MEM_64; | ||
1181 | ret = pbus_size_mem(bus, prefmask, prefmask, | ||
1182 | prefmask, prefmask, | ||
1168 | realloc_head ? 0 : additional_mem_size, | 1183 | realloc_head ? 0 : additional_mem_size, |
1169 | additional_mem_size, realloc_head)) | 1184 | additional_mem_size, realloc_head); |
1170 | mask = prefmask; /* Success, size non-prefetch only. */ | 1185 | |
1171 | else | 1186 | /* |
1172 | additional_mem_size += additional_mem_size; | 1187 | * If successful, all non-prefetchable resources |
1173 | pbus_size_mem(bus, mask, IORESOURCE_MEM, | 1188 | * and any 32-bit prefetchable resources will go in |
1189 | * the non-prefetchable window. | ||
1190 | */ | ||
1191 | if (ret == 0) { | ||
1192 | mask = prefmask; | ||
1193 | type2 = prefmask & ~IORESOURCE_MEM_64; | ||
1194 | type3 = prefmask & ~IORESOURCE_PREFETCH; | ||
1195 | } | ||
1196 | } | ||
1197 | |||
1198 | /* | ||
1199 | * If there is no 64-bit prefetchable window, compute the | ||
1200 | * size required to put all prefetchable resources in the | ||
1201 | * 32-bit prefetchable window (if there is one). | ||
1202 | */ | ||
1203 | if (!type2) { | ||
1204 | prefmask &= ~IORESOURCE_MEM_64; | ||
1205 | ret = pbus_size_mem(bus, prefmask, prefmask, | ||
1206 | prefmask, prefmask, | ||
1207 | realloc_head ? 0 : additional_mem_size, | ||
1208 | additional_mem_size, realloc_head); | ||
1209 | |||
1210 | /* | ||
1211 | * If successful, only non-prefetchable resources | ||
1212 | * will go in the non-prefetchable window. | ||
1213 | */ | ||
1214 | if (ret == 0) | ||
1215 | mask = prefmask; | ||
1216 | else | ||
1217 | additional_mem_size += additional_mem_size; | ||
1218 | |||
1219 | type2 = type3 = IORESOURCE_MEM; | ||
1220 | } | ||
1221 | |||
1222 | /* | ||
1223 | * Compute the size required to put everything else in the | ||
1224 | * non-prefetchable window. This includes: | ||
1225 | * | ||
1226 | * - all non-prefetchable resources | ||
1227 | * - 32-bit prefetchable resources if there's a 64-bit | ||
1228 | * prefetchable window or no prefetchable window at all | ||
1229 | * - 64-bit prefetchable resources if there's no | ||
1230 | * prefetchable window at all | ||
1231 | * | ||
1232 | * Note that the strategy in __pci_assign_resource() must | ||
1233 | * match that used here. Specifically, we cannot put a | ||
1234 | * 32-bit prefetchable resource in a 64-bit prefetchable | ||
1235 | * window. | ||
1236 | */ | ||
1237 | pbus_size_mem(bus, mask, IORESOURCE_MEM, type2, type3, | ||
1174 | realloc_head ? 0 : additional_mem_size, | 1238 | realloc_head ? 0 : additional_mem_size, |
1175 | additional_mem_size, realloc_head); | 1239 | additional_mem_size, realloc_head); |
1176 | break; | 1240 | break; |
@@ -1256,42 +1320,66 @@ static void __pci_bridge_assign_resources(const struct pci_dev *bridge, | |||
1256 | static void pci_bridge_release_resources(struct pci_bus *bus, | 1320 | static void pci_bridge_release_resources(struct pci_bus *bus, |
1257 | unsigned long type) | 1321 | unsigned long type) |
1258 | { | 1322 | { |
1259 | int idx; | 1323 | struct pci_dev *dev = bus->self; |
1260 | bool changed = false; | ||
1261 | struct pci_dev *dev; | ||
1262 | struct resource *r; | 1324 | struct resource *r; |
1263 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | | 1325 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | |
1264 | IORESOURCE_PREFETCH; | 1326 | IORESOURCE_PREFETCH | IORESOURCE_MEM_64; |
1327 | unsigned old_flags = 0; | ||
1328 | struct resource *b_res; | ||
1329 | int idx = 1; | ||
1265 | 1330 | ||
1266 | dev = bus->self; | 1331 | b_res = &dev->resource[PCI_BRIDGE_RESOURCES]; |
1267 | for (idx = PCI_BRIDGE_RESOURCES; idx <= PCI_BRIDGE_RESOURCE_END; | 1332 | |
1268 | idx++) { | 1333 | /* |
1269 | r = &dev->resource[idx]; | 1334 | * 1. if there is io port assign fail, will release bridge |
1270 | if ((r->flags & type_mask) != type) | 1335 | * io port. |
1271 | continue; | 1336 | * 2. if there is non pref mmio assign fail, release bridge |
1272 | if (!r->parent) | 1337 | * nonpref mmio. |
1273 | continue; | 1338 | * 3. if there is 64bit pref mmio assign fail, and bridge pref |
1274 | /* | 1339 | * is 64bit, release bridge pref mmio. |
1275 | * if there are children under that, we should release them | 1340 | * 4. if there is pref mmio assign fail, and bridge pref is |
1276 | * all | 1341 | * 32bit mmio, release bridge pref mmio |
1277 | */ | 1342 | * 5. if there is pref mmio assign fail, and bridge pref is not |
1278 | release_child_resources(r); | 1343 | * assigned, release bridge nonpref mmio. |
1279 | if (!release_resource(r)) { | 1344 | */ |
1280 | dev_printk(KERN_DEBUG, &dev->dev, | 1345 | if (type & IORESOURCE_IO) |
1281 | "resource %d %pR released\n", idx, r); | 1346 | idx = 0; |
1282 | /* keep the old size */ | 1347 | else if (!(type & IORESOURCE_PREFETCH)) |
1283 | r->end = resource_size(r) - 1; | 1348 | idx = 1; |
1284 | r->start = 0; | 1349 | else if ((type & IORESOURCE_MEM_64) && |
1285 | r->flags = 0; | 1350 | (b_res[2].flags & IORESOURCE_MEM_64)) |
1286 | changed = true; | 1351 | idx = 2; |
1287 | } | 1352 | else if (!(b_res[2].flags & IORESOURCE_MEM_64) && |
1288 | } | 1353 | (b_res[2].flags & IORESOURCE_PREFETCH)) |
1354 | idx = 2; | ||
1355 | else | ||
1356 | idx = 1; | ||
1357 | |||
1358 | r = &b_res[idx]; | ||
1359 | |||
1360 | if (!r->parent) | ||
1361 | return; | ||
1362 | |||
1363 | /* | ||
1364 | * if there are children under that, we should release them | ||
1365 | * all | ||
1366 | */ | ||
1367 | release_child_resources(r); | ||
1368 | if (!release_resource(r)) { | ||
1369 | type = old_flags = r->flags & type_mask; | ||
1370 | dev_printk(KERN_DEBUG, &dev->dev, "resource %d %pR released\n", | ||
1371 | PCI_BRIDGE_RESOURCES + idx, r); | ||
1372 | /* keep the old size */ | ||
1373 | r->end = resource_size(r) - 1; | ||
1374 | r->start = 0; | ||
1375 | r->flags = 0; | ||
1289 | 1376 | ||
1290 | if (changed) { | ||
1291 | /* avoiding touch the one without PREF */ | 1377 | /* avoiding touch the one without PREF */ |
1292 | if (type & IORESOURCE_PREFETCH) | 1378 | if (type & IORESOURCE_PREFETCH) |
1293 | type = IORESOURCE_PREFETCH; | 1379 | type = IORESOURCE_PREFETCH; |
1294 | __pci_setup_bridge(bus, type); | 1380 | __pci_setup_bridge(bus, type); |
1381 | /* for next child res under same bridge */ | ||
1382 | r->flags = old_flags; | ||
1295 | } | 1383 | } |
1296 | } | 1384 | } |
1297 | 1385 | ||
@@ -1470,7 +1558,7 @@ void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus) | |||
1470 | LIST_HEAD(fail_head); | 1558 | LIST_HEAD(fail_head); |
1471 | struct pci_dev_resource *fail_res; | 1559 | struct pci_dev_resource *fail_res; |
1472 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | | 1560 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | |
1473 | IORESOURCE_PREFETCH; | 1561 | IORESOURCE_PREFETCH | IORESOURCE_MEM_64; |
1474 | int pci_try_num = 1; | 1562 | int pci_try_num = 1; |
1475 | enum enable_type enable_local; | 1563 | enum enable_type enable_local; |
1476 | 1564 | ||