From nobody Tue Nov 26 14:31:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+54070+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+54070+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1581105985814507.1785034175273; Fri, 7 Feb 2020 12:06:25 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id 9FjYYY1788612xeyDnoZu6Lb; Fri, 07 Feb 2020 12:06:25 -0800 X-Received: from mga18.intel.com (mga18.intel.com []) by mx.groups.io with SMTP id smtpd.web09.10529.1581105978095314348 for ; Fri, 07 Feb 2020 12:06:24 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Feb 2020 12:06:24 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,414,1574150400"; d="scan'208";a="225644272" X-Received: from unknown (HELO PIDSBABIOS005.gar.corp.intel.com) ([10.223.9.183]) by fmsmga007.fm.intel.com with ESMTP; 07 Feb 2020 12:06:21 -0800 From: "Javeed, Ashraf" To: devel@edk2.groups.io Cc: Jian J Wang , Hao A Wu , Ray Ni Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] PciBusDxe: New PCI Express feature Completion Timeout Date: Sat, 8 Feb 2020 01:34:42 +0530 Message-Id: <20200207200447.10536-8-ashraf.javeed@intel.com> In-Reply-To: <20200207200447.10536-1-ashraf.javeed@intel.com> References: <20200207200447.10536-1-ashraf.javeed@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ashraf.javeed@intel.com X-Gm-Message-State: 8g9NN5PNeRdxD2OGYjAUc7NEx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1581105985; bh=nCspPPdw95kCbaLzj5fJWtU6gFWz6PacHo5z7WtD0v8=; h=Cc:Date:From:Reply-To:Subject:To; b=ozfz1SZIcLECrf5+DD0KVccHQNDsOTAempJFIhLwTvdIeGO1+XiUDXVDXQqmKGMgh1l JoU87SuCCTDsyG8JhpfREwDn5izdE02B2c8O2pF+CYVlsfwIkuTXuzoOTmwLHIK1qSfTN 0HZ2lXrg7P06aTRkso7ZPCYg7Aa/2UH/PVg= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2313 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 Cc: Jian J Wang Cc: Hao A Wu Cc: Ray Ni --- 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; }; =20 #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c b/MdeModul= ePkg/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; } =20 +/** + 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 t= he + device-specific platform policy, as well as in complaince with the PCI B= ase + specification Revision 4. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + + @retval EFI_SUCCESS processing of PCI feature CTO is s= uccessful. +**/ +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 =3D PciDevice->PciExpressCapabilityStructure.DeviceCap= ability2.Uint32; + if (!DeviceCap2.Bits.CompletionTimeoutRanges + && !DeviceCap2.Bits.CompletionTimeoutDisable + ) { + // + // device does not support the CTO mechanism, hence no override is app= licable + // + return EFI_SUCCESS; + } + + // + // override the device CTO values if applicable + // + if (PciDevice->SetupCTO.Act) { + // + // program the CTO range values + // + if (DeviceCap2.Bits.CompletionTimeoutRanges) { + CtoRangeValue =3D PCIE_COMPLETION_TIMEOUT_50US_50MS; + // + // in case if the supported CTO range and the requirement from platf= orm + // policy does not match, than the CTO range setting would be based = on + // this driver's implementation specific, and its rules are as follo= ws:- + // + // 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 de= fault + // 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; an= d the + // platform ask for Range C, or Range D values, than this implementa= tion + // will only program the Range B value for the duration of 65ms to 2= 10ms. + // + // 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 =3D 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 th= e default + // range value for the duration of 50us to 50ms. + // + if (IsCtoRangeB (PciDevice->SetupCTO.Support) + || IsCtoRangeC (PciDevice->SetupCTO.Support) + || IsCtoRangeD (PciDevice->SetupCTO.Support) + ) { + CtoRangeValue =3D 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 implementa= tion will + // only program the default range value for the duration of 50us= to 50ms. + // + if (IsCtoRangeA (PciDevice->SetupCTO.Support)) { + CtoRangeValue =3D PCIE_COMPLETION_TIMEOUT_50US_50MS; + } + + if (IsCtoRangeB (PciDevice->SetupCTO.Support)) { + CtoRangeValue =3D 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 implem= entation + // will only program the Range B value for the duration of 65ms = to 210ms. + // + if (IsCtoRangeC (PciDevice->SetupCTO.Support) + || IsCtoRangeD (PciDevice->SetupCTO.Support) + ) { + CtoRangeValue =3D PCIE_COMPLETION_TIMEOUT_65MS_210MS; + } + break; + + case PCIE_COMPLETION_TIMEOUT_RANGE_B_C_SUPPORTED: + if (IsCtoRangeA (PciDevice->SetupCTO.Support)) { + CtoRangeValue =3D PCIE_COMPLETION_TIMEOUT_50US_50MS; + } + + if (IsCtoRangeB (PciDevice->SetupCTO.Support) + || IsCtoRangeC (PciDevice->SetupCTO.Support) + ) { + CtoRangeValue =3D 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 implementat= ion will + // only program the Range C for the duration of 1s to 3.5s. + // + if (IsCtoRangeD (PciDevice->SetupCTO.Support)) { + CtoRangeValue =3D PCIE_COMPLETION_TIMEOUT_1S_3_5S; + } + break; + + case PCIE_COMPLETION_TIMEOUT_RANGE_B_C_D_SUPPORTED: + if (IsCtoRangeA (PciDevice->SetupCTO.Support)) { + CtoRangeValue =3D PCIE_COMPLETION_TIMEOUT_50US_50MS; + } + if (IsCtoRangeB (PciDevice->SetupCTO.Support) + || IsCtoRangeC (PciDevice->SetupCTO.Support) + || IsCtoRangeD (PciDevice->SetupCTO.Support) + ) { + CtoRangeValue =3D PciDevice->SetupCTO.Support; + } + break; + + case PCIE_COMPLETION_TIMEOUT_RANGE_A_B_SUPPORTED: + if (IsCtoRangeA (PciDevice->SetupCTO.Support) + || IsCtoRangeB (PciDevice->SetupCTO.Support) + ) { + CtoRangeValue =3D PciDevice->SetupCTO.Support; + } + if (IsCtoRangeC (PciDevice->SetupCTO.Support) + || IsCtoRangeD (PciDevice->SetupCTO.Support) + ) { + CtoRangeValue =3D 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 =3D PciDevice->SetupCTO.Support; + } + if (IsCtoRangeD (PciDevice->SetupCTO.Support)) { + CtoRangeValue =3D 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 =3D PciDevice->SetupCTO.Support; + } + break; + + default: + DEBUG (( + DEBUG_ERROR, + "Invalid CTO range: %d\n", + DeviceCap2.Bits.CompletionTimeoutRanges + )); + return EFI_INVALID_PARAMETER; + } + + if (PciDevice->SetupCTO.Support !=3D CtoRangeValue) { + PciDevice->SetupCTO.Support =3D 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 P= CI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, 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 r= egister + // + DeviceCap2.Uint32 =3D PciDevice->PciExpressCapabilityStructure.DeviceCap= ability2.Uint32; + if (DeviceCap2.Bits.CompletionTimeoutRanges + || DeviceCap2.Bits.CompletionTimeoutDisable) { + // + // device supports the CTO mechanism + // + DeviceCtl2.Uint16 =3D 0; + Offset =3D PciDevice->PciExpressCapabilityOffset + + OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2); + Status =3D PciDevice->PciIo.Pci.Read ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &DeviceCtl2.Uint16 + ); + ASSERT (Status =3D=3D EFI_SUCCESS); + } else { + // + // device does not support the CTO mechanism, hence no override perfor= med + // + 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 !=3D DeviceCtl2.Bits.CompletionTimeout= Value) { + DeviceCtl2.Bits.CompletionTimeoutValue =3D PciDevice->SetupCTO.Suppo= rt; + } + } else { + // + // disable the CTO mechanism in device + // + DeviceCtl2.Bits.CompletionTimeoutValue =3D 0; + DeviceCtl2.Bits.CompletionTimeoutDisable =3D 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 op= eration completes + // + OldTpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + + Status =3D 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 =3D Dev= iceCtl2.Uint16; + } else { + ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, Pc= iDevice->FunctionNumber, Offset); + } + return Status; +} + diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h b/MdeModul= ePkg/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 ); =20 +/** + 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 B= ase + specification Revision 4. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciConfigPhase for the PCI feature configuration = phases: + PciExpressFeatureSetupPhase & PciE= xpressFeatureEntendedSetupPhase + + @retval EFI_SUCCESS processing of PCI feature CTO is s= uccessful. +**/ +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 P= CI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, 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/MdeModule= Pkg/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 mPciExpressPl= atformPolicy =3D { // // 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 mPciExpressF= eatureInitializationList[] }, { PciExpressFeatureProgramPhase, PciExpressNoSnoop, ProgramNoS= noop + }, + { + PciExpressFeatureSetupPhase, PciExpressCto, SetupCompl= etionTimeout + }, + { + PciExpressFeatureProgramPhase, PciExpressCto, ProgramCom= pletionTimeout } }; =20 diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModul= ePkg/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 ( } } =20 +/** + 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_C= TO_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 mem= bers + // exclusively for the PCI Feature CTO + // + // .Override =3D 0 to skip this PCI feature CTO for the PCI device + // .Override =3D 1 to program this CTO PCI feature + // .Act =3D 1 to program the CTO range as per given device policy i= n .Support + // .Act =3D 0 to disable the CTO mechanism in the PCI device, CTO s= et to default range + // + switch (CtoSupport) { + case EFI_PCI_EXPRESS_CTO_AUTO: + PciDevice->SetupCTO.Override =3D 0; + break; + case EFI_PCI_EXPRESS_CTO_DEFAULT: + PciDevice->SetupCTO.Override =3D 1; + PciDevice->SetupCTO.Act =3D 1; + PciDevice->SetupCTO.Support =3D PCIE_COMPLETION_TIMEOUT_50US_50MS; + break; + case EFI_PCI_EXPRESS_CTO_RANGE_A1: + PciDevice->SetupCTO.Override =3D 1; + PciDevice->SetupCTO.Act =3D 1; + PciDevice->SetupCTO.Support =3D PCIE_COMPLETION_TIMEOUT_50US_100US; + break; + case EFI_PCI_EXPRESS_CTO_RANGE_A2: + PciDevice->SetupCTO.Override =3D 1; + PciDevice->SetupCTO.Act =3D 1; + PciDevice->SetupCTO.Support =3D PCIE_COMPLETION_TIMEOUT_1MS_10MS; + break; + case EFI_PCI_EXPRESS_CTO_RANGE_B1: + PciDevice->SetupCTO.Override =3D 1; + PciDevice->SetupCTO.Act =3D 1; + PciDevice->SetupCTO.Support =3D PCIE_COMPLETION_TIMEOUT_16MS_55MS; + break; + case EFI_PCI_EXPRESS_CTO_RANGE_B2: + PciDevice->SetupCTO.Override =3D 1; + PciDevice->SetupCTO.Act =3D 1; + PciDevice->SetupCTO.Support =3D PCIE_COMPLETION_TIMEOUT_65MS_210MS; + break; + case EFI_PCI_EXPRESS_CTO_RANGE_C1: + PciDevice->SetupCTO.Override =3D 1; + PciDevice->SetupCTO.Act =3D 1; + PciDevice->SetupCTO.Support =3D PCIE_COMPLETION_TIMEOUT_260MS_900MS; + break; + case EFI_PCI_EXPRESS_CTO_RANGE_C2: + PciDevice->SetupCTO.Override =3D 1; + PciDevice->SetupCTO.Act =3D 1; + PciDevice->SetupCTO.Support =3D PCIE_COMPLETION_TIMEOUT_1S_3_5S; + break; + case EFI_PCI_EXPRESS_CTO_RANGE_D1: + PciDevice->SetupCTO.Override =3D 1; + PciDevice->SetupCTO.Act =3D 1; + PciDevice->SetupCTO.Support =3D PCIE_COMPLETION_TIMEOUT_4S_13S; + break; + case EFI_PCI_EXPRESS_CTO_RANGE_D2: + PciDevice->SetupCTO.Override =3D 1; + PciDevice->SetupCTO.Act =3D 1; + PciDevice->SetupCTO.Support =3D PCIE_COMPLETION_TIMEOUT_17S_64S; + break; + case EFI_PCI_EXPRESS_CTO_DET_DISABLE: + PciDevice->SetupCTO.Override =3D 1; + PciDevice->SetupCTO.Act =3D 0; + PciDevice->SetupCTO.Support =3D PCIE_COMPLETION_TIMEOUT_50US_50MS; + break; + } +} + /** Generic routine to setup the PCI features as per its predetermined defau= lts. **/ @@ -253,6 +332,8 @@ SetupDefaultPciExpressDevicePolicy ( =20 PciDevice->SetupNS.Override =3D 0; =20 + PciDevice->SetupCTO.Override =3D 0; + } =20 /** @@ -360,6 +441,15 @@ GetPciExpressDevicePolicy ( PciDevice->SetupNS.Override =3D 0; } =20 + // + // set the device specific policy for Completion Timeout (CTO) + // + if (mPciExpressPlatformPolicy.Cto) { + SetDevicePolicyPciExpressCto (PciExpressDevicePolicy.CTOsupport, Pci= Device); + } else { + PciDevice->SetupCTO.Override =3D 0; + } + =20 DEBUG (( DEBUG_INFO, @@ -498,6 +588,34 @@ GetPciExpressMrrs ( return EFI_PCI_EXPRESS_NOT_APPLICABLE; } =20 +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; +} + =20 /** Notifies the platform about the current PCI Express state of the device. @@ -561,6 +679,19 @@ PciExpressPlatformNotifyDeviceState ( PciExDeviceConfiguration.DeviceCtlNoSnoop =3D EFI_PCI_EXPRESS_NOT_APPL= ICABLE; } =20 + // + // get the device-specific state for the PCIe CTO feature + // + if (mPciExpressPlatformPolicy.Cto) { + PciExDeviceConfiguration.CTOsupport =3D PciDevice->PciExpressCapabilit= yStructure.DeviceControl2.Bits.CompletionTimeoutDisable + ? EFI_PCI_EXPRESS_CTO_DET_DISABLE + : GetPciExpressCto ( + (UINT8)PciDevice->PciExpress= CapabilityStructure.DeviceControl2.Bits.CompletionTimeoutValue + ); + } else { + PciExDeviceConfiguration.CTOsupport =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; + } + =20 if (mPciExPlatformProtocol !=3D NULL) { return mPciExPlatformProtocol->NotifyDeviceState ( --=20 2.21.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#54070): https://edk2.groups.io/g/devel/message/54070 Mute This Topic: https://groups.io/mt/71063084/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-