public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Javeed, Ashraf" <ashraf.javeed@intel.com>
To: devel@edk2.groups.io
Cc: Jian J Wang <jian.j.wang@intel.com>,
	Hao A Wu <hao.a.wu@intel.com>, Ray Ni <ray.ni@intel.com>
Subject: [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	[thread overview]
Message-ID: <20200207200447.10536-8-ashraf.javeed@intel.com> (raw)
In-Reply-To: <20200207200447.10536-1-ashraf.javeed@intel.com>

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.javeed@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Ray Ni <ray.ni@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


  parent reply	other threads:[~2020-02-07 20:06 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-07 20:04 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] PciBusDxe: New PCI Express features Javeed, Ashraf
2020-02-07 20:04 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe: Setup for " Javeed, Ashraf
2020-02-07 20:04 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12] MdeModulePkg/PciBusDxe: Setup PCI Express init phase Javeed, Ashraf
2020-02-07 20:04 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12] PciBusDxe: New PCI Express feature Max_Payload_Size Javeed, Ashraf
2020-02-07 20:04 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 04/12] PciBusDxe: New PCI Express feature Max_Read_Req_Size Javeed, Ashraf
2020-02-07 20:04 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: New PCI Express feature Relax Ordering Javeed, Ashraf
2020-02-07 20:04 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 06/12] PciBusDxe: New PCI Express feature No-Snoop Javeed, Ashraf
2020-02-07 20:04 ` Javeed, Ashraf [this message]
2020-02-07 20:04 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12] PciBusDxe: New PCI Express feature AtomicOp Javeed, Ashraf
2020-02-07 20:04 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 09/12] PciBusDxe: New PCI Express feature LTR Javeed, Ashraf
2020-02-07 20:04 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 10/12] PciBusDxe: New PCI Express feature Extended Tag Javeed, Ashraf
2020-02-07 20:04 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 11/12] PciBusDxe: New PCI Express feature ASPM support Javeed, Ashraf
2020-02-07 20:04 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 12/12] PciBusDxe: New PCI Express feature Common CLock Config Javeed, Ashraf
     [not found] ` <15F1377EA7D1AA4F.7869@groups.io>
2020-02-07 20:16   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe: Setup for PCI Express features Javeed, Ashraf
2020-02-10  7:20     ` Ni, Ray
2020-02-10  8:26       ` Javeed, Ashraf
2020-02-10  8:37         ` Ni, Ray
2020-02-11  3:59           ` Javeed, Ashraf
     [not found] ` <15F137802DC889C4.7869@groups.io>
2020-02-07 20:18   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12] MdeModulePkg/PciBusDxe: Setup PCI Express init phase Javeed, Ashraf
2020-02-10  7:37     ` Ni, Ray
2020-02-10  8:32       ` Javeed, Ashraf
2020-02-10  8:46         ` Ni, Ray
2020-02-11  7:14           ` Javeed, Ashraf
     [not found] ` <15F137813D8F0C21.4848@groups.io>
2020-02-07 20:19   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12] PciBusDxe: New PCI Express feature Max_Payload_Size Javeed, Ashraf
     [not found] ` <15F13782B6D7AE2E.15938@groups.io>
2020-02-07 20:20   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 04/12] PciBusDxe: New PCI Express feature Max_Read_Req_Size Javeed, Ashraf
     [not found] ` <15F1378301D514E4.15938@groups.io>
2020-02-07 20:21   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: New PCI Express feature Relax Ordering Javeed, Ashraf
     [not found] ` <15F1378385E00982.18602@groups.io>
2020-02-07 20:22   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 06/12] PciBusDxe: New PCI Express feature No-Snoop Javeed, Ashraf
     [not found] ` <15F137842EDDF11D.15938@groups.io>
2020-02-07 20:24   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] PciBusDxe: New PCI Express feature Completion Timeout Javeed, Ashraf
     [not found] ` <15F13784AAF69472.18602@groups.io>
2020-02-07 20:25   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12] PciBusDxe: New PCI Express feature AtomicOp Javeed, Ashraf
     [not found]   ` <15F1389AA432C2B6.18602@groups.io>
2020-02-07 20:27     ` Javeed, Ashraf
     [not found] ` <15F13785436D3273.18602@groups.io>
2020-02-07 20:28   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 09/12] PciBusDxe: New PCI Express feature LTR Javeed, Ashraf
     [not found] ` <15F137861A640F9F.15938@groups.io>
2020-02-07 20:29   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 10/12] PciBusDxe: New PCI Express feature Extended Tag Javeed, Ashraf
     [not found] ` <15F13786546CB2AB.15938@groups.io>
2020-02-07 20:30   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 11/12] PciBusDxe: New PCI Express feature ASPM support Javeed, Ashraf
     [not found] ` <15F13786E92D19E9.15938@groups.io>
2020-02-07 20:31   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 12/12] PciBusDxe: New PCI Express feature Common CLock Config Javeed, Ashraf
2020-02-10  7:40 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] PciBusDxe: New PCI Express features Ni, Ray
2020-02-10  8:34   ` Javeed, Ashraf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200207200447.10536-8-ashraf.javeed@intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox