From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by mx.groups.io with SMTP id smtpd.web10.2459.1573616061076107845 for ; Tue, 12 Nov 2019 19:34:21 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 192.55.52.151, mailfrom: ashraf.javeed@intel.com) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga006.jf.intel.com ([10.7.209.51]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 12 Nov 2019 19:34:20 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.68,299,1569308400"; d="scan'208";a="207679742" Received: from fmsmsx106.amr.corp.intel.com ([10.18.124.204]) by orsmga006.jf.intel.com with ESMTP; 12 Nov 2019 19:34:20 -0800 Received: from fmsmsx163.amr.corp.intel.com (10.18.125.72) by FMSMSX106.amr.corp.intel.com (10.18.124.204) with Microsoft SMTP Server (TLS) id 14.3.439.0; Tue, 12 Nov 2019 19:34:19 -0800 Received: from bgsmsx109.gar.corp.intel.com (10.223.4.211) by fmsmsx163.amr.corp.intel.com (10.18.125.72) with Microsoft SMTP Server (TLS) id 14.3.439.0; Tue, 12 Nov 2019 19:34:19 -0800 Received: from bgsmsx101.gar.corp.intel.com ([169.254.1.49]) by BGSMSX109.gar.corp.intel.com ([169.254.10.25]) with mapi id 14.03.0439.000; Wed, 13 Nov 2019 09:04:16 +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 12/12] PciBusDxe: New PCI feature Completion Timeout Thread-Topic: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 12/12] PciBusDxe: New PCI feature Completion Timeout Thread-Index: AQHVkMaN6VS1wCSNyU6Zu2gy18U6hKeIhL7Q Date: Wed, 13 Nov 2019 03:34:16 +0000 Message-ID: <95C5C2B113DE604FB208120C742E982457917310@BGSMSX101.gar.corp.intel.com> References: <20191101150952.3340-1-ashraf.javeed@intel.com> <15D3127F5541064B.31784@groups.io> In-Reply-To: <15D3127F5541064B.31784@groups.io> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiMDhhYjdiMjYtMDQxOC00ZTE5LWIwODgtY2Q4YTk4MDRjNWU0IiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoiNzV4V3hHRFRuZWtzY2tveHA5Q2s0MmtqMGlmWmUxZTZ2Wjk5ZnBaOFROekdLd1NNXC9IWVN0S1dDZFVrNjBSQTUifQ== 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 is also uploaded in the following Repo for review:- https://github.com/ashrafj/edk2-staging/commit/fc451a1bb20fc774f7542ea06eb= 4e1b9ce369c0c Thanks Ashraf > -----Original Message----- > From: devel@edk2.groups.io On Behalf Of Javeed, > Ashraf > Sent: Friday, November 1, 2019 8:40 PM > To: devel@edk2.groups.io > Cc: Wang, Jian J ; Wu, Hao A = ; > Ni, Ray > Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 12/12] > PciBusDxe: New PCI feature Completion Timeout >=20 > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2313 >=20 > The code changes are made; as per the PCI Base Specification 4 Revision = 1; to > enable the configuration of new PCI feature Completion Timeout (CTO), wh= ich > enables the PCI function to wait on programmed duration for its transact= ions > before timeout, or disable its detection mechanism. >=20 > The code changes are made to configure only those PCI devices which are > requested to override by platform through the new PCI Platform protocol > interface for device-specific policies. The changes are made to also com= - ply > 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 >=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/PciFeatureSupport.c | 413 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++ > MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 84 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++ > 3 files changed, 498 insertions(+) >=20 > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h > index be1c341..b6ec14f 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/PciFeatureSupport.c > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c > index a7f0a2f..ba0de0d 100644 > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c > @@ -765,6 +765,294 @@ ProcessMaxReadReqSize ( > return EFI_SUCCESS; > } >=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 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: > + PciFeatureGetDevicePolicy & > + PciFeatureSetupPhase > + > + @retval EFI_SUCCESS processing of PCI feature CTO i= s successful. > +**/ > +EFI_STATUS > +ProcessCompletionTimeout ( > + IN PCI_IO_DEVICE *PciDevice, > + IN PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase > + ) > +{ > + PCI_REG_PCIE_DEVICE_CAPABILITY2 DeviceCap2; > + UINT8 CtoRangeValue; > + > + if (PciConfigPhase !=3D PciFeatureGetDevicePolicy) { > + // > + // no reprocessing required for device CTO configuration > + // > + return EFI_SUCCESS; > + } > + > + 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->PciExpStruct.DeviceCapability2.Uint3= 2; > + 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 Control register MaxPayloadSize register fie= ld; if > the hardware value is different than the intended value. > @@ -1061,6 +1349,119 @@ OverrideNoSnoop ( > return Status; > } >=20 > +/** > + 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 > +OverrideCompletionTimeout ( > + IN PCI_IO_DEVICE *PciDevice > + ) > +{ > + 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->PciExpStruct.DeviceCapability2.Uint3= 2; > + 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 > + ); > + if (EFI_ERROR(Status)){ > + DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl2 register (0x%x) = read > error!", > + Offset > + )); > + return Status; > + } > + } 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->PciExpStruct.DeviceControl2.Uint16 =3D DeviceCtl2.Uint16= ; > + } else { > + DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl2 register (0x%x) wr= ite > error!", > + Offset > + )); > + } > + return Status; > +} > + > /** > helper routine to dump the PCIe Device Port Type **/ @@ -1169,6 +157= 0,15 > @@ SetupDevicePciFeatures ( > OtherPciFeaturesConfigTable > ); > } > + // > + // process the PCI device CTO range values to be configured // if > + (SetupCompletionTimeout ()) { > + Status =3D ProcessCompletionTimeout ( > + PciDevice, > + PciConfigPhase > + ); > + } > DEBUG ((DEBUG_INFO, "]\n")); > return Status; > } > @@ -1278,6 +1688,9 @@ ProgramDevicePciFeatures ( > if (SetupNoSnoop ()) { > Status =3D OverrideNoSnoop (PciDevice); > } > + if (SetupCompletionTimeout()) { > + Status =3D OverrideCompletionTimeout (PciDevice); } > DEBUG (( DEBUG_INFO, "\n")); > return Status; > } > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c > index 47295cd..7ee0d7d 100644 > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c > @@ -549,6 +549,85 @@ SetDevicePolicyNoSnoop ( > } > } >=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_CONF_CTO_SUPPORT > + @param PciDevice A pointer to PCI_IO_DEVICE > +**/ > +VOID > +SetDevicePolicyCTO ( > + IN EFI_PCI_CONF_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_CONF_CTO_AUTO: > + PciDevice->SetupCTO.Override =3D 0; > + break; > + case EFI_PCI_CONF_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_CONF_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_CONF_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_CONF_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_CONF_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_CONF_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_CONF_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_CONF_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_CONF_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_CONF_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. > **/ > @@ -561,6 +640,7 @@ SetupDefaultsDevicePlatformPolicy ( > PciDevice->SetupMRRS =3D EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO; > PciDevice->SetupRO.Override =3D 0; > PciDevice->SetupNS.Override =3D 0; > + PciDevice->SetupCTO.Override =3D 0; > } >=20 > /** > @@ -606,6 +686,10 @@ GetPciDevicePlatformPolicyEx ( > // set the device specific policy for No-Snoop > // > SetDevicePolicyNoSnoop (PciPlatformExtendedPolicy.DeviceCtlNoSnoo= p, > PciIoDevice); > + // > + // set the device specific policy for Completion Timeout (CTO) > + // > + SetDevicePolicyCTO (PciPlatformExtendedPolicy.CTOsupport, > + PciIoDevice); >=20 > DEBUG (( > DEBUG_INFO, "[device policy: platform]" > -- > 2.21.0.windows.1 >=20 >=20 >=20