From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by mx.groups.io with SMTP id smtpd.web11.10726.1581107091814024278 for ; Fri, 07 Feb 2020 12:24:51 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 192.55.52.136, mailfrom: ashraf.javeed@intel.com) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Feb 2020 12:24:51 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,414,1574150400"; d="scan'208";a="232473135" Received: from fmsmsx106.amr.corp.intel.com ([10.18.124.204]) by orsmga003.jf.intel.com with ESMTP; 07 Feb 2020 12:24:50 -0800 Received: from fmsmsx601.amr.corp.intel.com (10.18.126.81) by FMSMSX106.amr.corp.intel.com (10.18.124.204) with Microsoft SMTP Server (TLS) id 14.3.439.0; Fri, 7 Feb 2020 12:24:50 -0800 Received: from fmsmsx601.amr.corp.intel.com (10.18.126.81) by fmsmsx601.amr.corp.intel.com (10.18.126.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5; Fri, 7 Feb 2020 12:24:50 -0800 Received: from bgsmsx102.gar.corp.intel.com (10.223.4.172) by fmsmsx601.amr.corp.intel.com (10.18.126.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.1.1713.5 via Frontend Transport; Fri, 7 Feb 2020 12:24:49 -0800 Received: from bgsmsx101.gar.corp.intel.com ([169.254.1.155]) by BGSMSX102.gar.corp.intel.com ([169.254.2.129]) with mapi id 14.03.0439.000; Sat, 8 Feb 2020 01:54:47 +0530 From: "Javeed, Ashraf" To: "devel@edk2.groups.io" , "Javeed, Ashraf" CC: "Wang, Jian J" , "Wu, Hao A" , "Ni, Ray" Subject: Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] PciBusDxe: New PCI Express feature Completion Timeout Thread-Topic: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] PciBusDxe: New PCI Express feature Completion Timeout Thread-Index: AQHV3fIdzPA0wp2vt02OewaBfgDgX6gQLQdw Date: Fri, 7 Feb 2020 20:24:46 +0000 Message-ID: <95C5C2B113DE604FB208120C742E9824579AAFF7@BGSMSX101.gar.corp.intel.com> References: <20200207200447.10536-1-ashraf.javeed@intel.com> <15F137842EDDF11D.15938@groups.io> In-Reply-To: <15F137842EDDF11D.15938@groups.io> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiMGMyYjg4YmItZGJlNC00MGYzLWJjYzAtYzRkMWNhZGU3NDVhIiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoieGUwS21qXC85VkZjY2pCWUphV2xlTUkxYm1oVlRqK1wvNEgrU0dQUFk1c3d6WVFMYlhFdnlGU01hRFBWY2hnVktQIn0= x-ctpclassification: CTP_NT dlp-product: dlpe-windows dlp-version: 11.2.0.6 dlp-reaction: no-action x-originating-ip: [10.223.10.10] MIME-Version: 1.0 Return-Path: ashraf.javeed@intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable This patch can also be viewed in the following repo:- https://github.com/ashrafj/edk2-staging/commit/7f0ea5bf87b220b8941bacac99f= 956948785571d Thanks Ashraf > -----Original Message----- > From: 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 ; Wu, Hao A = ; > Ni, Ray > Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] > PciBusDxe: New PCI Express feature Completion Timeout >=20 > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2313 >=20 > The code changes are made; as per the PCI Express Base Specification 4 R= evision > 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. >=20 > 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. >=20 > The code follows the below implementation specific rules in case the req= - > uested platform policy does not match with the device-specific capabilit= y > 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 defau= lt > 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 implementati= on > will only program the default range value for the duration of 50us t= o > 50ms > (3) if the device is capable of Range B only, or the ranges A & B; and i= f > 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 t= o > 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 wil= l > only program the Range C for the duration of 1s to 3.5s >=20 > 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(-) >=20 > 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/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; > } >=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 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 i= s 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 =3D > + 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 =3D PCIE_COMPLETION_TIMEOUT_50US_50MS; > + // > + // in case if the supported CTO range and the requirement from pl= atform > + // policy does not match, than the CTO range setting would be bas= ed on > + // this driver's implementation specific, and its rules are as fo= llows:- > + // > + // if device is capable of Range A only and if platform ask for a= ny 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 implementat= ion 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 impleme= ntation > + // will only program the Range B value for the duration of 65ms t= o 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 implementati= on 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 f= or 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 =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 impleme= ntation will > + // only program the default range value for the duration of 5= 0us 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 imp= lementation > + // will only program the Range B value for the duration of 65= ms 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 implemen= tation 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 th= e 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 =3D > + PciDevice->PciExpressCapabilityStructure.DeviceCapability2.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 > 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 !=3D > DeviceCtl2.Bits.CompletionTimeoutValue) { > + DeviceCtl2.Bits.CompletionTimeoutValue =3D PciDevice->SetupCTO.Su= pport; > + } > + } 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 > + operation 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 > +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 > ); >=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 Base > + specification Revision 4. > + > + @param PciDevice A pointer to the PCI_IO_DEVICE. > + @param PciConfigPhase for the PCI feature configurati= on phases: > + PciExpressFeatureSetupPhase & > + PciExpressFeatureEntendedSetupPhase > + > + @retval EFI_SUCCESS processing of PCI feature CTO i= s 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 th= e 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 =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 > mPciExpressFeatureInitializationList[] > }, > { > PciExpressFeatureProgramPhase, PciExpressNoSnoop, > ProgramNoSnoop > + }, > + { > + PciExpressFeatureSetupPhase, PciExpressCto, > SetupCompletionTimeout > + }, > + { > + PciExpressFeatureProgramPhase, PciExpressCto, > ProgramCompletionTimeout > } > }; >=20 > 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 ( > } > } >=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_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 =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 polic= y in .Support > + // .Act =3D 0 to disable the CTO mechanism in the PCI device, CT= O set 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 de= faults. > **/ > @@ -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, > PciDevice); > + } 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 devi= ce. > @@ -561,6 +679,19 @@ PciExpressPlatformNotifyDeviceState ( > PciExDeviceConfiguration.DeviceCtlNoSnoop =3D > EFI_PCI_EXPRESS_NOT_APPLICABLE; > } >=20 > + // > + // get the device-specific state for the PCIe CTO feature // if > + (mPciExpressPlatformPolicy.Cto) { > + PciExDeviceConfiguration.CTOsupport =3D PciDevice- > >PciExpressCapabilityStructure.DeviceControl2.Bits.CompletionTimeoutDisa= ble > + ? EFI_PCI_EXPRESS_CTO_DET_DIS= ABLE > + : GetPciExpressCto ( > + (UINT8)PciDevice- > >PciExpressCapabilityStructure.DeviceControl2.Bits.CompletionTimeoutValu= e > + ); } else { > + PciExDeviceConfiguration.CTOsupport =3D > + EFI_PCI_EXPRESS_NOT_APPLICABLE; } > + >=20 > if (mPciExPlatformProtocol !=3D NULL) { > return mPciExPlatformProtocol->NotifyDeviceState ( > -- > 2.21.0.windows.1 >=20 >=20 >=20