Skip to content

Commit b89f436

Browse files
committed
Improve PCIe resource assignment
- The PCIe MMIO regions on this SoC are absurdly small. Some demanding devices (like NVIDIA GPUs) need more than 16 MB of 32-bit non-prefetchable memory. To address this, carve out 256 MB at the top of MMIO64 for ECAM (128 MB), followed by MEM32 (128 MB, with 32-bit translation). MEM64 takes up the remaining space (768 MB), starting at the bottom of MMIO64 (to preserve the alignment). This should be enough to cover most use cases and allows for even a larger 512 MB prefetchable BAR. - Since all RCs share the same SMMU and ITS blocks, segments need distinct bus numbers so that Requester IDs don't overlap. With 128 MB of ECAM and 5 segments, this gives a spacing of 25 buses. Ideally, we would've encoded the segment number instead, but that doesn't seem possible here. - Sync ACPI and FDT with the updated resources. Signed-off-by: Mario Bălănică <[email protected]>
1 parent dd99440 commit b89f436

File tree

9 files changed

+383
-201
lines changed

9 files changed

+383
-201
lines changed

edk2-rockchip/Silicon/Rockchip/RK3588/AcpiTables/Mcfg.aslc

Lines changed: 0 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -23,80 +23,6 @@ RK3588_MCFG_TABLE Mcfg = {
2323
EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION
2424
),
2525
},
26-
{ // Main config space
27-
{
28-
PCIE_CFG_BASE (0),
29-
0, // PciSegmentNumber
30-
1, // PciBusMin
31-
1, // PciBusMax
32-
0 // Reserved
33-
},
34-
{
35-
PCIE_CFG_BASE (1),
36-
1, // PciSegmentNumber
37-
1, // PciBusMin
38-
1, // PciBusMax
39-
0 // Reserved
40-
},
41-
{
42-
PCIE_CFG_BASE (2),
43-
2, // PciSegmentNumber
44-
1, // PciBusMin
45-
1, // PciBusMax
46-
0 // Reserved
47-
},
48-
{
49-
PCIE_CFG_BASE (3),
50-
3, // PciSegmentNumber
51-
1, // PciBusMin
52-
1, // PciBusMax
53-
0 // Reserved
54-
},
55-
{
56-
PCIE_CFG_BASE (4),
57-
4, // PciSegmentNumber
58-
1, // PciBusMin
59-
1, // PciBusMax
60-
0 // Reserved
61-
}
62-
},
63-
{ // Root Port DBI config space (for Windows)
64-
{
65-
PCIE_DBI_BASE (0),
66-
0, // PciSegmentNumber
67-
0, // PciBusMin
68-
0, // PciBusMax
69-
0 // Reserved
70-
},
71-
{
72-
PCIE_DBI_BASE (1),
73-
1, // PciSegmentNumber
74-
0, // PciBusMin
75-
0, // PciBusMax
76-
0 // Reserved
77-
},
78-
{
79-
PCIE_DBI_BASE (2),
80-
2, // PciSegmentNumber
81-
0, // PciBusMin
82-
0, // PciBusMax
83-
0 // Reserved
84-
},
85-
{
86-
PCIE_DBI_BASE (3),
87-
3, // PciSegmentNumber
88-
0, // PciBusMin
89-
0, // PciBusMax
90-
0 // Reserved
91-
},
92-
{
93-
PCIE_DBI_BASE (4),
94-
4, // PciSegmentNumber
95-
0, // PciBusMin
96-
0, // PciBusMax
97-
0 // Reserved
98-
}
99-
}
10026
};
10127

10228
VOID *CONST ReferenceAcpiTable = &Mcfg;

edk2-rockchip/Silicon/Rockchip/RK3588/AcpiTables/Pcie.asl

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@
1616
Name (_UID, Segment) \
1717
Name (_SEG, Segment) \
1818
Method (_BBN) { \
19-
Return (PBMI) \
19+
If (PBOF) { \
20+
Return (PCIE_BUS_BASE (Segment) + PBMI) \
21+
} Else { \
22+
Return (PBMI) \
23+
} \
2024
} \
2125
Name (_STA, 0xF) \
2226
\
@@ -30,14 +34,34 @@
3034
Method (_CRS, 0, Serialized) { \
3135
Name (RBUF, ResourceTemplate () { \
3236
WORDBUSNUMBER_BUF (00, ResourceProducer) \
33-
DWORDMEMORY_BUF (01, ResourceProducer) \
37+
QWORDMEMORY_BUF (01, ResourceProducer) \
3438
QWORDMEMORY_BUF (02, ResourceProducer) \
3539
QWORDIO_BUF (03, ResourceProducer) \
3640
}) \
37-
WORD_SET (00, PBMI, PBMA - PBMI + 1, 0) \
38-
DWORD_SET (01, PCIE_MEM_BASE (Segment), PCIE_MEM_SIZE, 0) \
39-
QWORD_SET (02, PCIE_MEM64_BASE (Segment), PCIE_MEM64_SIZE, 0) \
40-
QWORD_SET (03, PCIE_IO_BASE, PCIE_IO_SIZE, PCIE_IO_XLATE (Segment)) \
41+
WORD_SET ( \
42+
00, \
43+
_BBN, \
44+
PBMA - PBMI + 1, \
45+
0 \
46+
) \
47+
QWORD_SET ( \
48+
01, \
49+
PCIE_MEM32_BUS_BASE, \
50+
PCIE_MEM32_SIZE, \
51+
PCIE_MEM32_TRANSLATION (Segment) \
52+
) \
53+
QWORD_SET ( \
54+
02, \
55+
PCIE_MEM64_BASE (Segment), \
56+
PCIE_MEM64_SIZE, \
57+
0 \
58+
) \
59+
QWORD_SET ( \
60+
03, \
61+
PCIE_IO_BUS_BASE, \
62+
PCIE_IO_SIZE, \
63+
PCIE_IO_TRANSLATION (Segment) \
64+
) \
4165
Return (RBUF) \
4266
} \
4367
\
@@ -61,7 +85,7 @@
6185
Name (RBUF, ResourceTemplate () { \
6286
QWORDMEMORY_BUF (00, ResourceProducer) \
6387
}) \
64-
QWORD_SET (00, PCIE_CFG_BASE (Segment), SIZE_256MB, 0) \
88+
QWORD_SET (00, PCIE_CFG_BASE (Segment), PCIE_CFG_SIZE , 0) \
6589
Return (RBUF) \
6690
} \
6791
} \
@@ -111,6 +135,7 @@
111135
Scope (\_SB_) {
112136
Name (PBMI, 0xABCD) // PCI Bus Minimum
113137
Name (PBMA, 0xABCD) // PCI Bus Maximum
138+
Name (PBOF, 1) // PCI Bus Offset
114139

115140
PCIE_ROOT_COMPLEX (0, 292)
116141
PCIE_ROOT_COMPLEX (1, 287)

edk2-rockchip/Silicon/Rockchip/RK3588/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.c

Lines changed: 89 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,9 @@ AcpiFixupPcieEcam (
218218
UINT32 PcieEcamMode;
219219
UINT8 PcieBusMin;
220220
UINT8 PcieBusMax;
221-
UINT8 McfgMainBusMin;
222-
BOOLEAN McfgSplitRootPort;
223-
BOOLEAN McfgSingleDevQuirk;
221+
BOOLEAN PcieBusOffset;
222+
BOOLEAN McfgDeviceFiltering;
223+
BOOLEAN McfgSplitConfigSpaces;
224224

225225
Index = 0;
226226
Status = AcpiLocateTableBySignature (
@@ -257,11 +257,21 @@ AcpiFixupPcieEcam (
257257

258258
switch (PcieEcamMode) {
259259
case ACPI_PCIE_ECAM_COMPAT_MODE_NXPMX6:
260-
PcieBusMin = 0;
261-
PcieBusMax = PCIE_BUS_LIMIT;
262-
McfgMainBusMin = 1;
263-
McfgSplitRootPort = TRUE;
264-
McfgSingleDevQuirk = FALSE;
260+
//
261+
// This workaround ought to filter duplicate devices on the primary
262+
// and secondary buses, but it appears that recent Windows versions
263+
// only do so for bus numbers 0 and 1.
264+
// Not all segments start at bus 0 anymore, since they need to be made
265+
// distinct to the SMMU & ITS (see Rk3588Pcie.h). However, these features
266+
// can't be enabled in Windows anyway, so we'll disable the bus offset and
267+
// let it reassign bus numbers from 0.
268+
// It's possible to enable PcieBusOffset by disabling McfgDeviceFiltering,
269+
// but this will hide the root port and may cause the system to lock-up
270+
// with certain endpoints that have broken CFG0 filtering.
271+
//
272+
PcieBusOffset = FALSE;
273+
McfgDeviceFiltering = !PcieBusOffset;
274+
McfgSplitConfigSpaces = TRUE;
265275

266276
Index = 0;
267277
Status = AcpiLocateTableBySignature (
@@ -285,44 +295,97 @@ AcpiFixupPcieEcam (
285295
break;
286296

287297
case ACPI_PCIE_ECAM_COMPAT_MODE_GRAVITON:
288-
PcieBusMin = 0;
289-
PcieBusMax = PCIE_BUS_LIMIT;
290-
McfgMainBusMin = 0;
291-
McfgSplitRootPort = FALSE;
292-
McfgSingleDevQuirk = FALSE;
298+
PcieBusOffset = TRUE;
299+
McfgDeviceFiltering = TRUE;
300+
McfgSplitConfigSpaces = FALSE;
293301

294302
CopyMem (McfgTable->Header.Header.OemId, "AMAZON", sizeof (McfgTable->Header.Header.OemId));
295303
McfgTable->Header.Header.OemTableId = SIGNATURE_64 ('G', 'R', 'A', 'V', 'I', 'T', 'O', 'N');
296304
break;
297305

298306
default: // ACPI_PCIE_ECAM_COMPAT_MODE_SINGLE_DEV
299-
PcieBusMin = 1;
300-
PcieBusMax = 1;
301-
McfgMainBusMin = 1;
302-
McfgSplitRootPort = FALSE;
303-
McfgSingleDevQuirk = TRUE;
307+
PcieBusOffset = TRUE;
308+
McfgDeviceFiltering = FALSE;
309+
McfgSplitConfigSpaces = FALSE;
304310
break;
305311
}
306312

307-
for (Index = 0; Index < ARRAY_SIZE (McfgTable->MainEntries); Index++) {
308-
if (McfgSingleDevQuirk) {
309-
if ((PcdGet32 (PcdPcieEcamCompliantSegmentsMask) & (1 << Index)) == 0) {
310-
McfgTable->MainEntries[Index].BaseAddress += 0x8000;
313+
PcieBusMin = 0;
314+
PcieBusMax = PCIE_BUS_COUNT - 1;
315+
316+
if (!McfgDeviceFiltering) {
317+
//
318+
// Skip the primary bus as it only spans a single function (root port)
319+
// and the remaining DBI region has to be filtered out.
320+
//
321+
PcieBusMin = 1;
322+
323+
if (!McfgSplitConfigSpaces) {
324+
//
325+
// It's not possible to have more than a single bus due to the
326+
// the device offset workaround below.
327+
//
328+
PcieBusMax = PcieBusMin;
329+
}
330+
}
331+
332+
for (Index = 0; Index < NUM_PCIE_CONTROLLER; Index++) {
333+
McfgTable->ConfigSpaces[0][Index].PciSegmentGroupNumber = Index;
334+
McfgTable->ConfigSpaces[0][Index].BaseAddress = PCIE_CFG_BASE (Index) + PCIE_BUS_BASE_OFFSET (Index);
335+
McfgTable->ConfigSpaces[0][Index].StartBusNumber = PcieBusMin;
336+
McfgTable->ConfigSpaces[0][Index].EndBusNumber = PcieBusMax;
337+
338+
if (PcieBusOffset) {
339+
McfgTable->ConfigSpaces[0][Index].BaseAddress -= PCIE_BUS_BASE_OFFSET (Index);
340+
McfgTable->ConfigSpaces[0][Index].StartBusNumber += PCIE_BUS_BASE (Index);
341+
McfgTable->ConfigSpaces[0][Index].EndBusNumber += PCIE_BUS_BASE (Index);
342+
}
343+
344+
if (McfgSplitConfigSpaces) {
345+
McfgTable->ConfigSpaces[1][Index].PciSegmentGroupNumber = McfgTable->ConfigSpaces[0][Index].PciSegmentGroupNumber;
346+
McfgTable->ConfigSpaces[1][Index].StartBusNumber = McfgTable->ConfigSpaces[0][Index].StartBusNumber;
347+
348+
if (McfgDeviceFiltering) {
349+
//
350+
// The OS is expected to filter devices on the primary and secondary
351+
// buses, so we can expose the root port in this entry (primary bus)
352+
// and remaining buses in the first entry.
353+
//
354+
McfgTable->ConfigSpaces[1][Index].BaseAddress = PCIE_DBI_BASE (Index);
355+
McfgTable->ConfigSpaces[1][Index].EndBusNumber = McfgTable->ConfigSpaces[1][Index].StartBusNumber;
356+
357+
McfgTable->ConfigSpaces[0][Index].StartBusNumber += 1;
358+
} else {
359+
//
360+
// The OS will not filter devices on any bus, so we can't expose
361+
// the root port. Use this entry for buses following secondary and
362+
// limit the first entry to the secondary bus only, so the device
363+
// offset workaround below can work.
364+
//
365+
McfgTable->ConfigSpaces[1][Index].BaseAddress = McfgTable->ConfigSpaces[0][Index].BaseAddress;
366+
McfgTable->ConfigSpaces[1][Index].StartBusNumber += 1;
367+
McfgTable->ConfigSpaces[1][Index].EndBusNumber = McfgTable->ConfigSpaces[0][Index].EndBusNumber;
368+
369+
McfgTable->ConfigSpaces[0][Index].EndBusNumber = McfgTable->ConfigSpaces[0][Index].StartBusNumber;
311370
}
312371
}
313372

314-
McfgTable->MainEntries[Index].StartBusNumber = McfgMainBusMin;
315-
McfgTable->MainEntries[Index].EndBusNumber = PcieBusMax;
373+
if (!McfgDeviceFiltering &&
374+
((PcdGet32 (PcdPcieEcamCompliantSegmentsMask) & (1 << Index)) == 0))
375+
{
376+
McfgTable->ConfigSpaces[0][Index].BaseAddress += 0x8000;
377+
}
316378
}
317379

318-
if (McfgSplitRootPort == FALSE) {
319-
McfgTable->Header.Header.Length -= sizeof (McfgTable->RootPortEntries);
380+
if (!McfgSplitConfigSpaces) {
381+
McfgTable->Header.Header.Length = OFFSET_OF (RK3588_MCFG_TABLE, ConfigSpaces[1]);
320382
}
321383

322384
AcpiUpdateChecksum ((UINT8 *)McfgTable, McfgTable->Header.Header.Length);
323385

324386
AcpiUpdateSdtNameInteger (mDsdtTable, "PBMI", PcieBusMin);
325387
AcpiUpdateSdtNameInteger (mDsdtTable, "PBMA", PcieBusMax);
388+
AcpiUpdateSdtNameInteger (mDsdtTable, "PBOF", PcieBusOffset);
326389

327390
return EFI_SUCCESS;
328391
}

0 commit comments

Comments
 (0)