@@ -713,12 +713,11 @@ static void pci_bridge_check_ranges(struct pci_bus *bus)
713
713
bus resource of a given type. Note: we intentionally skip
714
714
the bus resources which have already been assigned (that is,
715
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
719
int i ;
719
720
struct resource * r ;
720
- unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
721
- IORESOURCE_PREFETCH ;
722
721
723
722
pci_bus_for_each_resource (bus , r , i ) {
724
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
814
resource_size_t add_size , struct list_head * realloc_head )
816
815
{
817
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
819
resource_size_t size = 0 , size0 = 0 , size1 = 0 ;
820
820
resource_size_t children_add_size = 0 ;
821
821
resource_size_t min_align , align ;
@@ -907,6 +907,8 @@ static inline resource_size_t calculate_mem_align(resource_size_t *aligns,
907
907
* @bus : the bus
908
908
* @mask: mask the resource flag, then compare it with type
909
909
* @type: the type of free resource from bridge
910
+ * @type2: second match type
911
+ * @type3: third match type
910
912
* @min_size : the minimum memory window that must to be allocated
911
913
* @add_size : additional optional memory window
912
914
* @realloc_head : track the additional memory window on this list
@@ -915,16 +917,17 @@ static inline resource_size_t calculate_mem_align(resource_size_t *aligns,
915
917
* guarantees that all child resources fit in this size.
916
918
*/
917
919
static int pbus_size_mem (struct pci_bus * bus , unsigned long mask ,
918
- unsigned long type , resource_size_t min_size ,
919
- resource_size_t add_size ,
920
- struct list_head * realloc_head )
920
+ unsigned long type , unsigned long type2 ,
921
+ unsigned long type3 ,
922
+ resource_size_t min_size , resource_size_t add_size ,
923
+ struct list_head * realloc_head )
921
924
{
922
925
struct pci_dev * dev ;
923
926
resource_size_t min_align , align , size , size0 , size1 ;
924
927
resource_size_t aligns [14 ]; /* Alignments from 1Mb to 8Gb */
925
928
int order , max_order ;
926
- struct resource * b_res = find_free_bus_resource (bus , type );
927
- unsigned int mem64_mask = 0 ;
929
+ struct resource * b_res = find_free_bus_resource (bus ,
930
+ mask | IORESOURCE_PREFETCH , type ) ;
928
931
resource_size_t children_add_size = 0 ;
929
932
930
933
if (!b_res )
@@ -934,17 +937,16 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
934
937
max_order = 0 ;
935
938
size = 0 ;
936
939
937
- mem64_mask = b_res -> flags & IORESOURCE_MEM_64 ;
938
- b_res -> flags &= ~IORESOURCE_MEM_64 ;
939
-
940
940
list_for_each_entry (dev , & bus -> devices , bus_list ) {
941
941
int i ;
942
942
943
943
for (i = 0 ; i < PCI_NUM_RESOURCES ; i ++ ) {
944
944
struct resource * r = & dev -> resource [i ];
945
945
resource_size_t r_size ;
946
946
947
- if (r -> parent || (r -> flags & mask ) != type )
947
+ if (r -> parent || ((r -> flags & mask ) != type &&
948
+ (r -> flags & mask ) != type2 &&
949
+ (r -> flags & mask ) != type3 ))
948
950
continue ;
949
951
r_size = resource_size (r );
950
952
#ifdef CONFIG_PCI_IOV
@@ -981,7 +983,6 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
981
983
aligns [order ] += align ;
982
984
if (order > max_order )
983
985
max_order = order ;
984
- mem64_mask &= r -> flags & IORESOURCE_MEM_64 ;
985
986
986
987
if (realloc_head )
987
988
children_add_size += get_res_add_size (realloc_head , r );
@@ -1006,7 +1007,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
1006
1007
}
1007
1008
b_res -> start = min_align ;
1008
1009
b_res -> end = size0 + min_align - 1 ;
1009
- b_res -> flags |= IORESOURCE_STARTALIGN | mem64_mask ;
1010
+ b_res -> flags |= IORESOURCE_STARTALIGN ;
1010
1011
if (size1 > size0 && realloc_head ) {
1011
1012
add_to_list (realloc_head , bus -> self , b_res , size1 - size0 , min_align );
1012
1013
dev_printk (KERN_DEBUG , & bus -> self -> dev , "bridge window "
@@ -1122,8 +1123,9 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus,
1122
1123
struct list_head * realloc_head )
1123
1124
{
1124
1125
struct pci_dev * dev ;
1125
- unsigned long mask , prefmask ;
1126
+ unsigned long mask , prefmask , type2 = 0 , type3 = 0 ;
1126
1127
resource_size_t additional_mem_size = 0 , additional_io_size = 0 ;
1128
+ struct resource * b_res ;
1127
1129
1128
1130
list_for_each_entry (dev , & bus -> devices , bus_list ) {
1129
1131
struct pci_bus * b = dev -> subordinate ;
@@ -1168,15 +1170,37 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus,
1168
1170
has already been allocated by arch code, try
1169
1171
non-prefetchable range for both types of PCI memory
1170
1172
resources. */
1173
+ b_res = & bus -> self -> resource [PCI_BRIDGE_RESOURCES ];
1171
1174
mask = IORESOURCE_MEM ;
1172
1175
prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH ;
1173
- if (pbus_size_mem (bus , prefmask , prefmask ,
1176
+ if (b_res [2 ].flags & IORESOURCE_MEM_64 ) {
1177
+ prefmask |= IORESOURCE_MEM_64 ;
1178
+ if (pbus_size_mem (bus , prefmask , prefmask ,
1179
+ prefmask , prefmask ,
1174
1180
realloc_head ? 0 : additional_mem_size ,
1175
- additional_mem_size , realloc_head ))
1176
- mask = prefmask ; /* Success, size non-prefetch only. */
1177
- else
1178
- additional_mem_size += additional_mem_size ;
1179
- pbus_size_mem (bus , mask , IORESOURCE_MEM ,
1181
+ additional_mem_size , realloc_head )) {
1182
+ /*
1183
+ * Success, with pref mmio64,
1184
+ * next will size non-pref or
1185
+ * non-mmio64 */
1186
+ mask = prefmask ;
1187
+ type2 = prefmask & ~IORESOURCE_MEM_64 ;
1188
+ type3 = prefmask & ~IORESOURCE_PREFETCH ;
1189
+ }
1190
+ }
1191
+ if (!type2 ) {
1192
+ prefmask &= ~IORESOURCE_MEM_64 ;
1193
+ if (pbus_size_mem (bus , prefmask , prefmask ,
1194
+ prefmask , prefmask ,
1195
+ realloc_head ? 0 : additional_mem_size ,
1196
+ additional_mem_size , realloc_head )) {
1197
+ /* Success, next will size non-prefetch. */
1198
+ mask = prefmask ;
1199
+ } else
1200
+ additional_mem_size += additional_mem_size ;
1201
+ type2 = type3 = IORESOURCE_MEM ;
1202
+ }
1203
+ pbus_size_mem (bus , mask , IORESOURCE_MEM , type2 , type3 ,
1180
1204
realloc_head ? 0 : additional_mem_size ,
1181
1205
additional_mem_size , realloc_head );
1182
1206
break ;
@@ -1262,42 +1286,66 @@ static void __ref __pci_bridge_assign_resources(const struct pci_dev *bridge,
1262
1286
static void pci_bridge_release_resources (struct pci_bus * bus ,
1263
1287
unsigned long type )
1264
1288
{
1265
- int idx ;
1266
- bool changed = false;
1267
- struct pci_dev * dev ;
1289
+ struct pci_dev * dev = bus -> self ;
1268
1290
struct resource * r ;
1269
1291
unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
1270
- IORESOURCE_PREFETCH ;
1292
+ IORESOURCE_PREFETCH | IORESOURCE_MEM_64 ;
1293
+ unsigned old_flags = 0 ;
1294
+ struct resource * b_res ;
1295
+ int idx = 1 ;
1271
1296
1272
- dev = bus -> self ;
1273
- for (idx = PCI_BRIDGE_RESOURCES ; idx <= PCI_BRIDGE_RESOURCE_END ;
1274
- idx ++ ) {
1275
- r = & dev -> resource [idx ];
1276
- if ((r -> flags & type_mask ) != type )
1277
- continue ;
1278
- if (!r -> parent )
1279
- continue ;
1280
- /*
1281
- * if there are children under that, we should release them
1282
- * all
1283
- */
1284
- release_child_resources (r );
1285
- if (!release_resource (r )) {
1286
- dev_printk (KERN_DEBUG , & dev -> dev ,
1287
- "resource %d %pR released\n" , idx , r );
1288
- /* keep the old size */
1289
- r -> end = resource_size (r ) - 1 ;
1290
- r -> start = 0 ;
1291
- r -> flags = 0 ;
1292
- changed = true;
1293
- }
1294
- }
1297
+ b_res = & dev -> resource [PCI_BRIDGE_RESOURCES ];
1298
+
1299
+ /*
1300
+ * 1. if there is io port assign fail, will release bridge
1301
+ * io port.
1302
+ * 2. if there is non pref mmio assign fail, release bridge
1303
+ * nonpref mmio.
1304
+ * 3. if there is 64bit pref mmio assign fail, and bridge pref
1305
+ * is 64bit, release bridge pref mmio.
1306
+ * 4. if there is pref mmio assign fail, and bridge pref is
1307
+ * 32bit mmio, release bridge pref mmio
1308
+ * 5. if there is pref mmio assign fail, and bridge pref is not
1309
+ * assigned, release bridge nonpref mmio.
1310
+ */
1311
+ if (type & IORESOURCE_IO )
1312
+ idx = 0 ;
1313
+ else if (!(type & IORESOURCE_PREFETCH ))
1314
+ idx = 1 ;
1315
+ else if ((type & IORESOURCE_MEM_64 ) &&
1316
+ (b_res [2 ].flags & IORESOURCE_MEM_64 ))
1317
+ idx = 2 ;
1318
+ else if (!(b_res [2 ].flags & IORESOURCE_MEM_64 ) &&
1319
+ (b_res [2 ].flags & IORESOURCE_PREFETCH ))
1320
+ idx = 2 ;
1321
+ else
1322
+ idx = 1 ;
1323
+
1324
+ r = & b_res [idx ];
1325
+
1326
+ if (!r -> parent )
1327
+ return ;
1328
+
1329
+ /*
1330
+ * if there are children under that, we should release them
1331
+ * all
1332
+ */
1333
+ release_child_resources (r );
1334
+ if (!release_resource (r )) {
1335
+ type = old_flags = r -> flags & type_mask ;
1336
+ dev_printk (KERN_DEBUG , & dev -> dev , "resource %d %pR released\n" ,
1337
+ PCI_BRIDGE_RESOURCES + idx , r );
1338
+ /* keep the old size */
1339
+ r -> end = resource_size (r ) - 1 ;
1340
+ r -> start = 0 ;
1341
+ r -> flags = 0 ;
1295
1342
1296
- if (changed ) {
1297
1343
/* avoiding touch the one without PREF */
1298
1344
if (type & IORESOURCE_PREFETCH )
1299
1345
type = IORESOURCE_PREFETCH ;
1300
1346
__pci_setup_bridge (bus , type );
1347
+ /* for next child res under same bridge */
1348
+ r -> flags = old_flags ;
1301
1349
}
1302
1350
}
1303
1351
@@ -1476,7 +1524,7 @@ void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus)
1476
1524
LIST_HEAD (fail_head );
1477
1525
struct pci_dev_resource * fail_res ;
1478
1526
unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM |
1479
- IORESOURCE_PREFETCH ;
1527
+ IORESOURCE_PREFETCH | IORESOURCE_MEM_64 ;
1480
1528
int pci_try_num = 1 ;
1481
1529
enum enable_type enable_local ;
1482
1530
0 commit comments