Check PPB decode space and assign BAR accordingly

All child devices under a PPB must be in scope of its PPB's decode space.
Therefore, all PPB checks the decode capability and downgrades its child
devices' resources accordingly.

Signed-off-by: Aiden Park <aiden.park@intel.com>
This commit is contained in:
Aiden Park 2020-08-11 15:33:34 -07:00 committed by Maurice Ma
parent 8aeed6fd9a
commit 21e9d1a51e
3 changed files with 142 additions and 25 deletions

View File

@ -11,6 +11,14 @@
#include <IndustryStandard/Pci.h>
#include <Guid/PciRootBridgeInfoGuid.h>
#define EFI_BRIDGE_IO32_DECODE_SUPPORTED 0x0001
#define EFI_BRIDGE_PMEM32_DECODE_SUPPORTED 0x0002
#define EFI_BRIDGE_PMEM64_DECODE_SUPPORTED 0x0004
#define EFI_BRIDGE_IO16_DECODE_SUPPORTED 0x0008
#define EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED 0x0010
#define EFI_BRIDGE_MEM64_DECODE_SUPPORTED 0x0020
#define EFI_BRIDGE_MEM32_DECODE_SUPPORTED 0x0040
//
// The PCI Command register bits owned by PCI Bus driver.
//
@ -106,6 +114,11 @@ struct _PCI_IO_DEVICE {
//
PCI_BAR PciBar[PCI_MAX_BAR];
//
// The resource decode the bridge supports
//
UINT32 Decodes;
//
// Bus number ranges for a PCI Root Bridge device
//

View File

@ -135,7 +135,6 @@ PciParseBar (
UINT32 Mask;
EFI_STATUS Status;
PCI_BAR_TYPE BarType;
PCI_ENUM_POLICY_INFO *EnumPolicy;
BarType = PciBarTypeUnknown;
OriginalValue = 0;
@ -160,7 +159,6 @@ PciParseBar (
return Offset + 4;
}
EnumPolicy = (PCI_ENUM_POLICY_INFO *)PcdGetPtr (PcdPciEnumPolicyInfo);
PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;
if ((Value & 0x01) != 0) {
//
@ -172,7 +170,7 @@ PciParseBar (
//
// It is a IO32 bar
//
if ((EnumPolicy != NULL) && (EnumPolicy->DowngradeIo32 == 0)) {
if ((PciIoDevice->Decodes & EFI_BRIDGE_IO32_DECODE_SUPPORTED) != 0) {
BarType = PciBarTypeIo32;
} else {
BarType = PciBarTypeIo16;
@ -232,13 +230,13 @@ PciParseBar (
//
case 0x04:
if ((Value & 0x08) != 0) {
if ((EnumPolicy != NULL) && (EnumPolicy->DowngradePMem64 == 0)) {
if ((PciIoDevice->Decodes & EFI_BRIDGE_PMEM64_DECODE_SUPPORTED) != 0) {
BarType = PciBarTypePMem64;
} else {
BarType = PciBarTypePMem32;
}
} else {
if ((EnumPolicy != NULL) && (EnumPolicy->DowngradeMem64 == 0)) {
if ((PciIoDevice->Decodes & EFI_BRIDGE_MEM64_DECODE_SUPPORTED) != 0) {
BarType = PciBarTypeMem64;
} else {
BarType = PciBarTypeMem32;
@ -364,6 +362,16 @@ InitializePpb (
PciExpressWrite32 (PciIoDevice->Address + 0x24, 0x0000FFFF);
PciExpressWrite32 (PciIoDevice->Address + 0x28, 0xFFFFFFFF);
PciExpressWrite32 (PciIoDevice->Address + 0x2C, 0x00000000);
//
// Don't support use io32 as for now
//
PciExpressWrite32 (PciIoDevice->Address + 0x30, 0x0000FFFF);
//
// Force Interrupt line to zero for cards that come up randomly
//
PciExpressWrite8 (PciIoDevice->Address + 0x3C, 0x00);
}
/**
@ -399,7 +407,8 @@ CreatePciIoDevice (
CopyMem (& (PciIoDevice->Pci), Pci, sizeof (PCI_TYPE00));
}
PciIoDevice->IsPciExp = FALSE;
PciIoDevice->Decodes = 0;
PciIoDevice->IsPciExp = FALSE;
PciIoDevice->PciExpressCapabilityOffset = 0;
if (FeaturePcdGet (PcdAriSupport) || FeaturePcdGet (PcdSrIovSupport)) {
InitializePciExpCapability (PciIoDevice);
@ -454,6 +463,13 @@ GatherDeviceInfo (
Value = PciExpressRead16 (PCI_EXPRESS_LIB_ADDRESS (Bus, Device, Func, PCI_COMMAND_OFFSET));
PciExpressWrite16 (PCI_EXPRESS_LIB_ADDRESS (Bus, Device, Func, PCI_COMMAND_OFFSET), 0);
//
// Inherit parent decode capability
//
if (PciIoDevice->Parent != NULL) {
PciIoDevice->Decodes = PciIoDevice->Parent->Decodes;
}
//
// Start to parse the bars
//
@ -499,6 +515,12 @@ GatherPpbInfo (
)
{
PCI_IO_DEVICE *PciIoDevice;
EFI_STATUS Status;
UINT8 Value;
UINT8 Temp;
UINT32 PMemBaseLimit;
UINT16 PrefetchableMemoryBase;
UINT16 PrefetchableMemoryLimit;
PciIoDevice = CreatePciIoDevice (
Bridge,
@ -514,6 +536,69 @@ GatherPpbInfo (
PciExpressAnd16 (PciIoDevice->Address + PCI_COMMAND_OFFSET, (UINT16)~EFI_PCI_COMMAND_BITS_OWNED);
PciExpressAnd16 (PciIoDevice->Address + PCI_BRIDGE_CONTROL_REGISTER_OFFSET, (UINT16)~EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);
//
// Test whether it support 32 decode or not
//
Temp = PciExpressRead8 (PciIoDevice->Address + 0x1C);
PciExpressWrite8 (PciIoDevice->Address + 0x1C, 0xFF);
Value = PciExpressRead8 (PciIoDevice->Address + 0x1C);
PciExpressWrite8 (PciIoDevice->Address + 0x1C, Temp);
if (Value != 0) {
if ((Value & 0x01) != 0) {
PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;
} else {
PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
}
}
Status = BarExisted (
PciIoDevice,
0x24,
NULL,
&PMemBaseLimit
);
//
// Test if it supports 64 memory or not
//
// The bottom 4 bits of both the Prefetchable Memory Base and Prefetchable Memory Limit
// registers:
// 0 - the bridge supports only 32 bit addresses.
// 1 - the bridge supports 64-bit addresses.
//
PrefetchableMemoryBase = (UINT16)(PMemBaseLimit & 0xffff);
PrefetchableMemoryLimit = (UINT16)(PMemBaseLimit >> 16);
if (!EFI_ERROR (Status) &&
(PrefetchableMemoryBase & 0x000f) == 0x0001 &&
(PrefetchableMemoryLimit & 0x000f) == 0x0001) {
Status = BarExisted (
PciIoDevice,
0x28,
NULL,
NULL
);
if (!EFI_ERROR (Status)) {
PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
} else {
PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
}
}
//
// Memory 32 code is required for ppb
//
PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
//
// Make sure that PPB is in scope of parent's decode capability
//
if (PciIoDevice->Parent != NULL) {
PciIoDevice->Decodes &= PciIoDevice->Parent->Decodes;
}
//
// PPB can have two BARs
//
@ -1332,9 +1417,9 @@ PciProgramResources (
**/
EFI_STATUS
PciScanRootBridges (
IN PCI_ENUM_POLICY_INFO *EnumPolicy,
OUT PCI_IO_DEVICE **RootBridge,
OUT UINT8 *RootBridgeCount
IN CONST PCI_ENUM_POLICY_INFO *EnumPolicy,
OUT PCI_IO_DEVICE **RootBridge,
OUT UINT8 *RootBridgeCount
)
{
UINT32 Address;
@ -1347,6 +1432,11 @@ PciScanRootBridges (
UINT16 EndIndex;
UINT8 Count;
UINT8 BusLimit;
UINT32 RootBridgeDecodes;
if ((EnumPolicy == NULL) || (RootBridge == NULL) || (RootBridgeCount == NULL)) {
return EFI_INVALID_PARAMETER;
}
Bridge = (PCI_IO_DEVICE *)PciAllocatePool (sizeof (PCI_IO_DEVICE));
ZeroMem (Bridge, sizeof (PCI_IO_DEVICE));
@ -1371,13 +1461,26 @@ PciScanRootBridges (
// Use PCI_MAX_BUS if the enum policy has no multiple buses.
//
BusLimit = PCI_MAX_BUS;
EnumPolicy = (PCI_ENUM_POLICY_INFO *)PcdGetPtr (PcdPciEnumPolicyInfo);
if ((EnumPolicy != NULL) && (EnumPolicy->NumOfBus > 1)) {
if (EnumPolicy->NumOfBus > 1) {
if (StartIndex != EndIndex) {
BusLimit = EnumPolicy->BusScanItems[EnumPolicy->NumOfBus - 1];
}
}
//
// Root bridge decode space
//
RootBridgeDecodes = 0xFFFFFFFF;
if (EnumPolicy->DowngradeIo32 != 0) {
RootBridgeDecodes &= (UINT32)~(EFI_BRIDGE_IO32_DECODE_SUPPORTED);
}
if (EnumPolicy->DowngradeMem64 != 0) {
RootBridgeDecodes &= (UINT32)~(EFI_BRIDGE_MEM64_DECODE_SUPPORTED);
}
if (EnumPolicy->DowngradePMem64 != 0) {
RootBridgeDecodes &= (UINT32)~(EFI_BRIDGE_PMEM64_DECODE_SUPPORTED);
}
for (Index = StartIndex; Index <= EndIndex; Index++) {
if (EnumPolicy->BusScanType == BusScanTypeList) {
Bus = EnumPolicy->BusScanItems[Index];
@ -1388,6 +1491,7 @@ PciScanRootBridges (
Address = PCI_EXPRESS_LIB_ADDRESS (Bus, 0, 0, 0);
if (PciExpressRead16 (Address) != 0xFFFF) {
Root = CreatePciIoDevice (NULL, NULL, (UINT8)Bus, 0, 0);
Root->Decodes = RootBridgeDecodes;
Root->BusNumberRanges.BusBase = (UINT8)Bus;
Root->BusNumberRanges.BusLimit = BusLimit;
@ -1532,17 +1636,19 @@ PciEnumeration (
IN VOID *MemPool
)
{
PCI_ENUM_POLICY_INFO *EnumPolicy;
PCI_IO_DEVICE *RootBridge;
UINT64 BaseAddress;
UINT8 RootBridgeCount;
CONST PCI_ENUM_POLICY_INFO *EnumPolicy;
PCI_IO_DEVICE *RootBridge;
UINT64 BaseAddress;
UINT8 RootBridgeCount;
EFI_STATUS Status;
SetAllocationPool (MemPool);
EnumPolicy = (PCI_ENUM_POLICY_INFO *)PcdGetPtr (PcdPciEnumPolicyInfo);
ASSERT (EnumPolicy != NULL);
RootBridgeCount = 0;
PciScanRootBridges (EnumPolicy, &RootBridge, &RootBridgeCount);
Status = PciScanRootBridges (EnumPolicy, &RootBridge, &RootBridgeCount);
ASSERT_EFI_ERROR (Status);
ASSERT (RootBridgeCount > 0);
BaseAddress = PcdGet32 (PcdPciResourceIoBase);

View File

@ -32,11 +32,10 @@ PciIovParseVfBar (
IN UINTN BarIndex
)
{
UINT32 Value;
UINT32 OriginalValue;
UINT32 Mask;
EFI_STATUS Status;
PCI_ENUM_POLICY_INFO *EnumPolicy;
UINT32 Value;
UINT32 OriginalValue;
UINT32 Mask;
EFI_STATUS Status;
//
// Ensure it is called properly
@ -68,7 +67,6 @@ PciIovParseVfBar (
return Offset + 4;
}
EnumPolicy = (PCI_ENUM_POLICY_INFO *)PcdGetPtr (PcdPciEnumPolicyInfo);
PciIoDevice->VfPciBar[BarIndex].Offset = (UINT16) Offset;
if ((Value & 0x01) != 0) {
//
@ -115,13 +113,13 @@ PciIovParseVfBar (
//
case 0x04:
if ((Value & 0x08) != 0) {
if ((EnumPolicy != NULL) && (EnumPolicy->DowngradePMem64 == 0)) {
if ((PciIoDevice->Decodes & EFI_BRIDGE_PMEM64_DECODE_SUPPORTED) != 0) {
PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem64;
} else {
PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypePMem32;
}
} else {
if ((EnumPolicy != NULL) && (EnumPolicy->DowngradeMem64 == 0)) {
if ((PciIoDevice->Decodes & EFI_BRIDGE_MEM64_DECODE_SUPPORTED) != 0) {
PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem64;
} else {
PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeMem32;