This patch can also be viewed in the following repo:- https://github.com/ashrafj/edk2-staging/commit/7f0ea5bf87b220b8941bacac99f956948785571d
Thanks Ashraf > -----Original Message----- > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed, > Ashraf > Sent: Saturday, February 8, 2020 1:35 AM > To: devel@edk2.groups.io > Cc: Wang, Jian J <jian.j.w...@intel.com>; Wu, Hao A <hao.a...@intel.com>; > Ni, Ray <ray...@intel.com> > Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] > PciBusDxe: New PCI Express feature Completion Timeout > > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2313 > > The code changes are made; as per the PCI Express Base Specification 4 > Revision > 1; to enable the configuration of PCI Express feature Completion Timeout > (CTO), > that enables the PCI function to wait on programmed dura- tion for its > transactions before timeout, or disable its detection mecha- nism. > > The code changes are made to configure only those PCI devices which are > requested by platform for override through the new PCI Express Platform > protocol interface for device-specific policies. The changes are made to also > comply with the device-specific capability attributes. > > The code follows the below implementation specific rules in case the req- > uested platform policy does not match with the device-specific capability > attributes:- > (1) if device is capable of Range A only and if platform ask for any of > ranges B, C, D; than this implementation will only program the default > range value for the duration of 50us to 50ms > (2) if device is capable of Range B, or range B & C, or Ranges B, C & D > only and if the platform ask for the Range A; than this implementation > will only program the default range value for the duration of 50us to > 50ms > (3) if the device is capable of Range B only, or the ranges A & B; and if > the platform ask for Range C, or Range D values, than this implement- > ation will only program the Range B value for the duration of 65ms to > 210ms > (4) if the device is capable of Ranges B & C, or Ranges A, B, and C; and > if the platform ask for Range D values; than this implementation will > only program the Range C for the duration of 1s to 3.5s > > Signed-off-by: Ashraf Javeed <ashraf.jav...@intel.com> > Cc: Jian J Wang <jian.j.w...@intel.com> > Cc: Hao A Wu <hao.a...@intel.com> > Cc: Ray Ni <ray...@intel.com> > --- > MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h | 1 + > MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c | 387 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h | 35 > +++++++++++++++++++++++++++++++++++ > MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c | 8 +++++++- > MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 131 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > + > 5 files changed, 561 insertions(+), 1 deletion(-) > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h > index e610b52..9b03c12 100644 > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h > @@ -294,6 +294,7 @@ struct _PCI_IO_DEVICE { > UINT8 SetupMRRS; > PCI_FEATURE_POLICY SetupRO; > PCI_FEATURE_POLICY SetupNS; > + PCI_FEATURE_POLICY SetupCTO; > }; > > #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ diff --git > a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c > index df85366..f3f4d39 100644 > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c > @@ -521,3 +521,390 @@ ProgramNoSnoop ( > return Status; > } > > +/** > + To determine the CTO Range A values > + > + @param CtoValue input CTO range value from 0 to 14 > + @retval TRUE the given CTO value belongs to Range A > + FALSE the given value does not belong to Range A > +**/ > +BOOLEAN > +IsCtoRangeA ( > + IN UINT8 CtoValue > + ) > +{ > + switch (CtoValue) { > + case PCIE_COMPLETION_TIMEOUT_50US_100US: > + case PCIE_COMPLETION_TIMEOUT_1MS_10MS: > + return TRUE; > + } > + return FALSE; > +} > + > +/** > + To determine the CTO Range B values > + > + @param CtoValue input CTO range value from 0 to 14 > + @retval TRUE the given CTO value belongs to Range B > + FALSE the given value does not belong to Range B > +**/ > +BOOLEAN > +IsCtoRangeB ( > + IN UINT8 CtoValue > + ) > +{ > + switch (CtoValue) { > + case PCIE_COMPLETION_TIMEOUT_16MS_55MS: > + case PCIE_COMPLETION_TIMEOUT_65MS_210MS: > + return TRUE; > + } > + return FALSE; > +} > + > +/** > + To determine the CTO Range C values > + > + @param CtoValue input CTO range value from 0 to 14 > + @retval TRUE the given CTO value belongs to Range C > + FALSE the given value does not belong to Range C > +**/ > +BOOLEAN > +IsCtoRangeC ( > + IN UINT8 CtoValue > + ) > +{ > + switch (CtoValue) { > + case PCIE_COMPLETION_TIMEOUT_260MS_900MS: > + case PCIE_COMPLETION_TIMEOUT_1S_3_5S: > + return TRUE; > + } > + return FALSE; > +} > + > +/** > + To determine the CTO Range D values > + > + @param CtoValue input CTO range value from 0 to 14 > + @retval TRUE the given CTO value belongs to Range D > + FALSE the given value does not belong to Range D > +**/ > +BOOLEAN > +IsCtoRangeD ( > + IN UINT8 CtoValue > + ) > +{ > + switch (CtoValue) { > + case PCIE_COMPLETION_TIMEOUT_4S_13S: > + case PCIE_COMPLETION_TIMEOUT_17S_64S: > + return TRUE; > + } > + return FALSE; > +} > + > +/** > + The main routine which setup the PCI feature Completion Timeout as > +per the > + device-specific platform policy, as well as in complaince with the > +PCI Base > + specification Revision 4. > + > + @param PciDevice A pointer to the PCI_IO_DEVICE. > + > + @retval EFI_SUCCESS processing of PCI feature CTO is > successful. > +**/ > +EFI_STATUS > +SetupCompletionTimeout ( > + IN PCI_IO_DEVICE *PciDevice, > + IN VOID *PciExFeatureConfiguration > + ) > +{ > + PCI_REG_PCIE_DEVICE_CAPABILITY2 DeviceCap2; > + UINT8 CtoRangeValue; > + > + if (!PciDevice->SetupCTO.Override) { > + // > + // No override of CTO is required for this device > + // > + return EFI_SUCCESS; > + } > + > + // > + // determine the CTO range values as per its device capability > + register // > + DeviceCap2.Uint32 = > + PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Uint32; > + if (!DeviceCap2.Bits.CompletionTimeoutRanges > + && !DeviceCap2.Bits.CompletionTimeoutDisable > + ) { > + // > + // device does not support the CTO mechanism, hence no override is > applicable > + // > + return EFI_SUCCESS; > + } > + > + // > + // override the device CTO values if applicable // if > + (PciDevice->SetupCTO.Act) { > + // > + // program the CTO range values > + // > + if (DeviceCap2.Bits.CompletionTimeoutRanges) { > + CtoRangeValue = PCIE_COMPLETION_TIMEOUT_50US_50MS; > + // > + // in case if the supported CTO range and the requirement from platform > + // policy does not match, than the CTO range setting would be based on > + // this driver's implementation specific, and its rules are as > follows:- > + // > + // if device is capable of Range A only and if platform ask for any of > + // ranges B, C, D; than this implementation will only program the > default > + // range value for the duration of 50us to 50ms. > + // > + // if device is capable of Range B, or range B & C, or Ranges B, C & D > only > + // and if the platform ask for the Range A; than this implementation > will > + // only program the default range value for the duration of 50us to > 50ms. > + // > + // if the device is capable of Range B only, or the ranges A & B; and > the > + // platform ask for Range C, or Range D values, than this > implementation > + // will only program the Range B value for the duration of 65ms to > 210ms. > + // > + // if the device is capable of Ranges B & C, or Ranges A, B, and C; and > + // if the platform ask for Range D values; than this implementation > will > + // only program the Range C for the duration of 1s to 3.5s. > + // > + > + switch (DeviceCap2.Bits.CompletionTimeoutRanges) { > + case PCIE_COMPLETION_TIMEOUT_RANGE_A_SUPPORTED: > + if (IsCtoRangeA (PciDevice->SetupCTO.Support)) { > + CtoRangeValue = PciDevice->SetupCTO.Support; > + } > + // > + // if device is capable of Range A only and if platform ask for > any of > + // ranges B, C, D; than this implementation will only program the > default > + // range value for the duration of 50us to 50ms. > + // > + if (IsCtoRangeB (PciDevice->SetupCTO.Support) > + || IsCtoRangeC (PciDevice->SetupCTO.Support) > + || IsCtoRangeD (PciDevice->SetupCTO.Support) > + ) { > + CtoRangeValue = PCIE_COMPLETION_TIMEOUT_50US_50MS; > + } > + break; > + > + case PCIE_COMPLETION_TIMEOUT_RANGE_B_SUPPORTED: > + // > + // if device is capable of Range B, or range B & C, or Ranges B, C > & D only > + // and if the platform ask for the Range A; than this > implementation will > + // only program the default range value for the duration of 50us > to 50ms. > + // > + if (IsCtoRangeA (PciDevice->SetupCTO.Support)) { > + CtoRangeValue = PCIE_COMPLETION_TIMEOUT_50US_50MS; > + } > + > + if (IsCtoRangeB (PciDevice->SetupCTO.Support)) { > + CtoRangeValue = PciDevice->SetupCTO.Support; > + } > + // > + // if the device is capable of Range B only, or the ranges A & B; > and the > + // platform ask for Range C, or Range D values, than this > implementation > + // will only program the Range B value for the duration of 65ms to > 210ms. > + // > + if (IsCtoRangeC (PciDevice->SetupCTO.Support) > + || IsCtoRangeD (PciDevice->SetupCTO.Support) > + ) { > + CtoRangeValue = PCIE_COMPLETION_TIMEOUT_65MS_210MS; > + } > + break; > + > + case PCIE_COMPLETION_TIMEOUT_RANGE_B_C_SUPPORTED: > + if (IsCtoRangeA (PciDevice->SetupCTO.Support)) { > + CtoRangeValue = PCIE_COMPLETION_TIMEOUT_50US_50MS; > + } > + > + if (IsCtoRangeB (PciDevice->SetupCTO.Support) > + || IsCtoRangeC (PciDevice->SetupCTO.Support) > + ) { > + CtoRangeValue = PciDevice->SetupCTO.Support; > + } > + // > + // if the device is capable of Ranges B & C, or Ranges A, B, and > C; and > + // if the platform ask for Range D values; than this > implementation will > + // only program the Range C for the duration of 1s to 3.5s. > + // > + if (IsCtoRangeD (PciDevice->SetupCTO.Support)) { > + CtoRangeValue = PCIE_COMPLETION_TIMEOUT_1S_3_5S; > + } > + break; > + > + case PCIE_COMPLETION_TIMEOUT_RANGE_B_C_D_SUPPORTED: > + if (IsCtoRangeA (PciDevice->SetupCTO.Support)) { > + CtoRangeValue = PCIE_COMPLETION_TIMEOUT_50US_50MS; > + } > + if (IsCtoRangeB (PciDevice->SetupCTO.Support) > + || IsCtoRangeC (PciDevice->SetupCTO.Support) > + || IsCtoRangeD (PciDevice->SetupCTO.Support) > + ) { > + CtoRangeValue = PciDevice->SetupCTO.Support; > + } > + break; > + > + case PCIE_COMPLETION_TIMEOUT_RANGE_A_B_SUPPORTED: > + if (IsCtoRangeA (PciDevice->SetupCTO.Support) > + || IsCtoRangeB (PciDevice->SetupCTO.Support) > + ) { > + CtoRangeValue = PciDevice->SetupCTO.Support; > + } > + if (IsCtoRangeC (PciDevice->SetupCTO.Support) > + || IsCtoRangeD (PciDevice->SetupCTO.Support) > + ) { > + CtoRangeValue = PCIE_COMPLETION_TIMEOUT_65MS_210MS; > + } > + break; > + > + case PCIE_COMPLETION_TIMEOUT_RANGE_A_B_C_SUPPORTED: > + if (IsCtoRangeA (PciDevice->SetupCTO.Support) > + || IsCtoRangeB (PciDevice->SetupCTO.Support) > + || IsCtoRangeC (PciDevice->SetupCTO.Support) > + ) { > + CtoRangeValue = PciDevice->SetupCTO.Support; > + } > + if (IsCtoRangeD (PciDevice->SetupCTO.Support)) { > + CtoRangeValue = PCIE_COMPLETION_TIMEOUT_1S_3_5S; > + } > + break; > + > + case PCIE_COMPLETION_TIMEOUT_RANGE_A_B_C_D_SUPPORTED: > + if (IsCtoRangeA (PciDevice->SetupCTO.Support) > + || IsCtoRangeB (PciDevice->SetupCTO.Support) > + || IsCtoRangeC (PciDevice->SetupCTO.Support) > + || IsCtoRangeD (PciDevice->SetupCTO.Support) > + ) { > + CtoRangeValue = PciDevice->SetupCTO.Support; > + } > + break; > + > + default: > + DEBUG (( > + DEBUG_ERROR, > + "Invalid CTO range: %d\n", > + DeviceCap2.Bits.CompletionTimeoutRanges > + )); > + return EFI_INVALID_PARAMETER; > + } > + > + if (PciDevice->SetupCTO.Support != CtoRangeValue) { > + PciDevice->SetupCTO.Support = CtoRangeValue; > + } > + } > + DEBUG (( DEBUG_INFO, "CTO enable: %d, CTO range: 0x%x,", > + PciDevice->SetupCTO.Act, > + PciDevice->SetupCTO.Support > + )); > + } > + return EFI_SUCCESS; > +} > + > +/** > + Overrides the PCI Device Control2 register Completion Timeout range; > +if > + the hardware value is different than the intended value. > + > + @param PciDevice A pointer to the PCI_IO_DEVICE instance. > + > + @retval EFI_SUCCESS The data was read from or written to the PCI > device. > + @retval EFI_UNSUPPORTED The address range specified by Offset, Width, > and Count is not > + valid for the PCI configuration header of > the PCI controller. > + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. > + > +**/ > +EFI_STATUS > +ProgramCompletionTimeout ( > + IN PCI_IO_DEVICE *PciDevice, > + IN VOID *PciExFeatureConfiguration > + ) > +{ > + PCI_REG_PCIE_DEVICE_CONTROL2 DeviceCtl2; > + PCI_REG_PCIE_DEVICE_CAPABILITY2 DeviceCap2; > + UINT32 Offset; > + EFI_STATUS Status; > + EFI_TPL OldTpl; > + > + if (!PciDevice->SetupCTO.Override) { > + // > + // No override of CTO is required for this device > + // > + DEBUG (( DEBUG_INFO, "CTO skipped,")); > + return EFI_SUCCESS; > + } > + > + // > + // to program the CTO range values, determine in its device > + capability register // > + DeviceCap2.Uint32 = > + PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Uint32; > + if (DeviceCap2.Bits.CompletionTimeoutRanges > + || DeviceCap2.Bits.CompletionTimeoutDisable) { > + // > + // device supports the CTO mechanism > + // > + DeviceCtl2.Uint16 = 0; > + Offset = PciDevice->PciExpressCapabilityOffset + > + OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2); > + Status = PciDevice->PciIo.Pci.Read ( > + &PciDevice->PciIo, > + EfiPciIoWidthUint16, > + Offset, > + 1, > + &DeviceCtl2.Uint16 > + ); > + ASSERT (Status == EFI_SUCCESS); > + } else { > + // > + // device does not support the CTO mechanism, hence no override > performed > + // > + DEBUG (( DEBUG_INFO, "CTO n/a,")); > + return EFI_SUCCESS; > + } > + > + // > + // override the device CTO values if applicable // if > + (PciDevice->SetupCTO.Act) { > + // > + // program the CTO range values > + // > + if (PciDevice->SetupCTO.Support != > DeviceCtl2.Bits.CompletionTimeoutValue) { > + DeviceCtl2.Bits.CompletionTimeoutValue = PciDevice->SetupCTO.Support; > + } > + } else { > + // > + // disable the CTO mechanism in device > + // > + DeviceCtl2.Bits.CompletionTimeoutValue = 0; > + DeviceCtl2.Bits.CompletionTimeoutDisable = 1; } DEBUG (( > + DEBUG_INFO, "CTO disable: %d, CTO range: 0x%x,", > + DeviceCtl2.Bits.CompletionTimeoutDisable, > + DeviceCtl2.Bits.CompletionTimeoutValue > + )); > + > + // > + // Raise TPL to high level to disable timer interrupt while the write > + operation completes // OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); > + > + Status = PciDevice->PciIo.Pci.Write ( > + &PciDevice->PciIo, > + EfiPciIoWidthUint16, > + Offset, > + 1, > + &DeviceCtl2.Uint16 > + ); > + // > + // Restore TPL to its original level > + // > + gBS->RestoreTPL (OldTpl); > + > + if (!EFI_ERROR(Status)) { > + PciDevice->PciExpressCapabilityStructure.DeviceControl2.Uint16 = > +DeviceCtl2.Uint16; > + } else { > + ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, > +PciDevice->FunctionNumber, Offset); > + } > + return Status; > +} > + > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h > index ee636ce..2ee7d4d 100644 > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h > @@ -133,4 +133,39 @@ ProgramNoSnoop ( > IN VOID *PciExFeatureConfiguration > ); > > +/** > + The main routine which process the PCI feature Completion Timeout as > +per the > + device-specific platform policy, as well as in complaince with the > +PCI Base > + specification Revision 4. > + > + @param PciDevice A pointer to the PCI_IO_DEVICE. > + @param PciConfigPhase for the PCI feature configuration > phases: > + PciExpressFeatureSetupPhase & > + PciExpressFeatureEntendedSetupPhase > + > + @retval EFI_SUCCESS processing of PCI feature CTO is > successful. > +**/ > +EFI_STATUS > +SetupCompletionTimeout ( > + IN PCI_IO_DEVICE *PciDevice, > + IN VOID *PciExFeatureConfiguration > + ); > + > +/** > + Overrides the PCI Device Control2 register Completion Timeout range; > +if > + the hardware value is different than the intended value. > + > + @param PciDevice A pointer to the PCI_IO_DEVICE instance. > + > + @retval EFI_SUCCESS The data was read from or written to the PCI > device. > + @retval EFI_UNSUPPORTED The address range specified by Offset, Width, > and Count is not > + valid for the PCI configuration header of > the PCI controller. > + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. > + > +**/ > +EFI_STATUS > +ProgramCompletionTimeout ( > + IN PCI_IO_DEVICE *PciDevice, > + IN VOID *PciExFeatureConfiguration > + ); > + > #endif > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c > index d264d13..d4459f3 100644 > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c > @@ -74,7 +74,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY > mPciExpressPlatformPolicy = { > // > // support for PCI Express feature - Completion Timeout > // > - FALSE, > + TRUE, > // > // support for PCI Express feature - Clock Power Management > // > @@ -119,6 +119,12 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT > mPciExpressFeatureInitializationList[] > }, > { > PciExpressFeatureProgramPhase, PciExpressNoSnoop, > ProgramNoSnoop > + }, > + { > + PciExpressFeatureSetupPhase, PciExpressCto, > SetupCompletionTimeout > + }, > + { > + PciExpressFeatureProgramPhase, PciExpressCto, > ProgramCompletionTimeout > } > }; > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c > index 954ce16..1afea19 100644 > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c > @@ -228,6 +228,85 @@ SetDevicePolicyPciExpressNs ( > } > } > > +/** > + Routine to set the device-specific policy for the PCI feature CTO > +value range > + or disable > + > + @param CtoSupport value corresponding to data type > EFI_PCI_EXPRESS_CTO_SUPPORT > + @param PciDevice A pointer to PCI_IO_DEVICE > +**/ > +VOID > +SetDevicePolicyPciExpressCto ( > + IN EFI_PCI_EXPRESS_CTO_SUPPORT CtoSupport, > + OUT PCI_IO_DEVICE *PciDevice > +) > +{ > + // > + // implementation specific rules for the usage of PCI_FEATURE_POLICY > +members > + // exclusively for the PCI Feature CTO > + // > + // .Override = 0 to skip this PCI feature CTO for the PCI device > + // .Override = 1 to program this CTO PCI feature > + // .Act = 1 to program the CTO range as per given device policy in > .Support > + // .Act = 0 to disable the CTO mechanism in the PCI device, CTO set to > default range > + // > + switch (CtoSupport) { > + case EFI_PCI_EXPRESS_CTO_AUTO: > + PciDevice->SetupCTO.Override = 0; > + break; > + case EFI_PCI_EXPRESS_CTO_DEFAULT: > + PciDevice->SetupCTO.Override = 1; > + PciDevice->SetupCTO.Act = 1; > + PciDevice->SetupCTO.Support = > PCIE_COMPLETION_TIMEOUT_50US_50MS; > + break; > + case EFI_PCI_EXPRESS_CTO_RANGE_A1: > + PciDevice->SetupCTO.Override = 1; > + PciDevice->SetupCTO.Act = 1; > + PciDevice->SetupCTO.Support = > PCIE_COMPLETION_TIMEOUT_50US_100US; > + break; > + case EFI_PCI_EXPRESS_CTO_RANGE_A2: > + PciDevice->SetupCTO.Override = 1; > + PciDevice->SetupCTO.Act = 1; > + PciDevice->SetupCTO.Support = PCIE_COMPLETION_TIMEOUT_1MS_10MS; > + break; > + case EFI_PCI_EXPRESS_CTO_RANGE_B1: > + PciDevice->SetupCTO.Override = 1; > + PciDevice->SetupCTO.Act = 1; > + PciDevice->SetupCTO.Support = > PCIE_COMPLETION_TIMEOUT_16MS_55MS; > + break; > + case EFI_PCI_EXPRESS_CTO_RANGE_B2: > + PciDevice->SetupCTO.Override = 1; > + PciDevice->SetupCTO.Act = 1; > + PciDevice->SetupCTO.Support = > PCIE_COMPLETION_TIMEOUT_65MS_210MS; > + break; > + case EFI_PCI_EXPRESS_CTO_RANGE_C1: > + PciDevice->SetupCTO.Override = 1; > + PciDevice->SetupCTO.Act = 1; > + PciDevice->SetupCTO.Support = > PCIE_COMPLETION_TIMEOUT_260MS_900MS; > + break; > + case EFI_PCI_EXPRESS_CTO_RANGE_C2: > + PciDevice->SetupCTO.Override = 1; > + PciDevice->SetupCTO.Act = 1; > + PciDevice->SetupCTO.Support = PCIE_COMPLETION_TIMEOUT_1S_3_5S; > + break; > + case EFI_PCI_EXPRESS_CTO_RANGE_D1: > + PciDevice->SetupCTO.Override = 1; > + PciDevice->SetupCTO.Act = 1; > + PciDevice->SetupCTO.Support = PCIE_COMPLETION_TIMEOUT_4S_13S; > + break; > + case EFI_PCI_EXPRESS_CTO_RANGE_D2: > + PciDevice->SetupCTO.Override = 1; > + PciDevice->SetupCTO.Act = 1; > + PciDevice->SetupCTO.Support = PCIE_COMPLETION_TIMEOUT_17S_64S; > + break; > + case EFI_PCI_EXPRESS_CTO_DET_DISABLE: > + PciDevice->SetupCTO.Override = 1; > + PciDevice->SetupCTO.Act = 0; > + PciDevice->SetupCTO.Support = > PCIE_COMPLETION_TIMEOUT_50US_50MS; > + break; > + } > +} > + > /** > Generic routine to setup the PCI features as per its predetermined > defaults. > **/ > @@ -253,6 +332,8 @@ SetupDefaultPciExpressDevicePolicy ( > > PciDevice->SetupNS.Override = 0; > > + PciDevice->SetupCTO.Override = 0; > + > } > > /** > @@ -360,6 +441,15 @@ GetPciExpressDevicePolicy ( > PciDevice->SetupNS.Override = 0; > } > > + // > + // set the device specific policy for Completion Timeout (CTO) > + // > + if (mPciExpressPlatformPolicy.Cto) { > + SetDevicePolicyPciExpressCto (PciExpressDevicePolicy.CTOsupport, > PciDevice); > + } else { > + PciDevice->SetupCTO.Override = 0; > + } > + > > DEBUG (( > DEBUG_INFO, > @@ -498,6 +588,34 @@ GetPciExpressMrrs ( > return EFI_PCI_EXPRESS_NOT_APPLICABLE; } > > +EFI_PCI_EXPRESS_CTO_SUPPORT > +GetPciExpressCto ( > + IN UINT8 Cto > + ) > +{ > + switch (Cto) { > + case PCIE_COMPLETION_TIMEOUT_50US_50MS: > + return EFI_PCI_EXPRESS_CTO_DEFAULT; > + case PCIE_COMPLETION_TIMEOUT_50US_100US: > + return EFI_PCI_EXPRESS_CTO_RANGE_A1; > + case PCIE_COMPLETION_TIMEOUT_1MS_10MS: > + return EFI_PCI_EXPRESS_CTO_RANGE_A2; > + case PCIE_COMPLETION_TIMEOUT_16MS_55MS: > + return EFI_PCI_EXPRESS_CTO_RANGE_B1; > + case PCIE_COMPLETION_TIMEOUT_65MS_210MS: > + return EFI_PCI_EXPRESS_CTO_RANGE_B2; > + case PCIE_COMPLETION_TIMEOUT_260MS_900MS: > + return EFI_PCI_EXPRESS_CTO_RANGE_C1; > + case PCIE_COMPLETION_TIMEOUT_1S_3_5S: > + return EFI_PCI_EXPRESS_CTO_RANGE_C2; > + case PCIE_COMPLETION_TIMEOUT_4S_13S: > + return EFI_PCI_EXPRESS_CTO_RANGE_D1; > + case PCIE_COMPLETION_TIMEOUT_17S_64S: > + return EFI_PCI_EXPRESS_CTO_RANGE_D2; > + } > + return EFI_PCI_EXPRESS_NOT_APPLICABLE; } > + > > /** > Notifies the platform about the current PCI Express state of the device. > @@ -561,6 +679,19 @@ PciExpressPlatformNotifyDeviceState ( > PciExDeviceConfiguration.DeviceCtlNoSnoop = > EFI_PCI_EXPRESS_NOT_APPLICABLE; > } > > + // > + // get the device-specific state for the PCIe CTO feature // if > + (mPciExpressPlatformPolicy.Cto) { > + PciExDeviceConfiguration.CTOsupport = PciDevice- > >PciExpressCapabilityStructure.DeviceControl2.Bits.CompletionTimeoutDisable > + ? EFI_PCI_EXPRESS_CTO_DET_DISABLE > + : GetPciExpressCto ( > + (UINT8)PciDevice- > >PciExpressCapabilityStructure.DeviceControl2.Bits.CompletionTimeoutValue > + ); } else { > + PciExDeviceConfiguration.CTOsupport = > + EFI_PCI_EXPRESS_NOT_APPLICABLE; } > + > > if (mPciExPlatformProtocol != NULL) { > return mPciExPlatformProtocol->NotifyDeviceState ( > -- > 2.21.0.windows.1 > > > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#54082): https://edk2.groups.io/g/devel/message/54082 Mute This Topic: https://groups.io/mt/71063569/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-