public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] PciBusDxe: New PCI Express features
@ 2020-02-07 20:04 Javeed, Ashraf
  2020-02-07 20:04 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe: Setup for " Javeed, Ashraf
                   ` (24 more replies)
  0 siblings, 25 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:04 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

The PciBusDxe is enhanced to initialize 10 PCI Express features (patch
index 3 to 12).
All these PCI Express features attributes are defined based on the new
PCI Express Platform Protocol definition (as per its ECR draft version
0.8): https://bugzilla.tianocore.org/show_bug.cgi?id=1954.
For MPS, MRRS:-
    https://bugzilla.tianocore.org/show_bug.cgi?id=2194
For RO, NS, CTO:-
    https://bugzilla.tianocore.org/show_bug.cgi?id=2313
For AtomicOp, Extended Tag, LTR:-
    https://bugzilla.tianocore.org/show_bug.cgi?id=2499
For ASPM, CCC:-
    https://bugzilla.tianocore.org/show_bug.cgi?id=2500

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>


Ashraf Javeed (12):
  MdeModulePkg/PciBusDxe: Setup for PCI Express features
  MdeModulePkg/PciBusDxe: Setup PCI Express init phase
  PciBusDxe: New PCI Express feature Max_Payload_Size
  PciBusDxe: New PCI Express feature Max_Read_Req_Size
  PciBusDxe: New PCI Express feature Relax Ordering
  PciBusDxe: New PCI Express feature No-Snoop
  PciBusDxe: New PCI Express feature Completion Timeout
  PciBusDxe: New PCI Express feature AtomicOp
  PciBusDxe: New PCI Express feature LTR
  PciBusDxe: New PCI Express feature Extended Tag
  PciBusDxe: New PCI Express feature ASPM support
  PciBusDxe: New PCI Express feature Common CLock Config

 MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c               |    6 ++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h               |   25 ++++++++++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf          |   11 ++++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c     |  181 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
 MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c |   12 +++++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c   | 2178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h   |  399 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c    | 1019 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h    |  304 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c   |  902 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h   |  119 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 11 files changed, 5116 insertions(+), 40 deletions(-)
 create mode 100644 MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
 create mode 100644 MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
 create mode 100644 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
 create mode 100644 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
 create mode 100644 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
 create mode 100644 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h

-- 
2.21.0.windows.1


^ permalink raw reply	[flat|nested] 36+ messages in thread

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe: Setup for PCI Express features
  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 ` 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
                   ` (23 subsequent siblings)
  24 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:04 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

References:-
  https://bugzilla.tianocore.org/show_bug.cgi?id=1954
  https://bugzilla.tianocore.org/show_bug.cgi?id=2194
  https://bugzilla.tianocore.org/show_bug.cgi?id=2313
  https://bugzilla.tianocore.org/show_bug.cgi?id=2499
  https://bugzilla.tianocore.org/show_bug.cgi?id=2500

This code change represents the preparation of common code setup for the
new PCI Express features initialization, utilizing the new PCI Express
Platform / Override Protocol.
The new set of source files are as follows:-
  new file:   /PciFeatureSupport.c
  new file:   /PciFeatureSupport.h
  new file:   /PciPlatformSupport.c
  new file:   /PciPlatformSupport.h

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.c               |   6 +++++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h               |  12 ++++++++++--
 MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf          |   9 ++++++++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c |  12 +++++++++++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c    | 891 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h    | 226 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c   | 302 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h   |  87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 1540 insertions(+), 5 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
index b020ce5..714101c 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
@@ -8,7 +8,7 @@
   PCI Root Bridges. So it means platform needs install PCI Root Bridge IO protocol for each
   PCI Root Bus and install PCI Host Bridge Resource Allocation Protocol.
 
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -284,6 +284,10 @@ PciBusDriverBindingStart (
           (VOID **) &gPciOverrideProtocol
           );
   }
+  //
+  // get the PCI Express Protocol or the PCI Express Override Protocol
+  //
+  GetPciExpressProtocol ();
 
   if (mIoMmuProtocol == NULL) {
     gBS->LocateProtocol (
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index 504a1b1..225229d 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -1,7 +1,7 @@
 /** @file
   Header files and data structures needed by PCI Bus module.
 
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -42,6 +42,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <IndustryStandard/Pci.h>
 #include <IndustryStandard/PeImage.h>
 #include <IndustryStandard/Acpi.h>
+#include <Protocol/PciExpressOverride.h>
+#include <Protocol/PciExpressPlatform.h>
 
 typedef struct _PCI_IO_DEVICE              PCI_IO_DEVICE;
 typedef struct _PCI_BAR                    PCI_BAR;
@@ -79,6 +81,8 @@ typedef enum {
 #include "PciPowerManagement.h"
 #include "PciHotPlugSupport.h"
 #include "PciLib.h"
+#include "PciPlatformSupport.h"
+#include "PciFeatureSupport.h"
 
 #define VGABASE1  0x3B0
 #define VGALIMIT1 0x3BB
@@ -263,9 +267,13 @@ struct _PCI_IO_DEVICE {
 
   BOOLEAN                                   IsPciExp;
   //
-  // For SR-IOV
+  // For PCI Express Capability List Structure
   //
   UINT8                                     PciExpressCapabilityOffset;
+  PCI_CAPABILITY_PCIEXP                     PciExpressCapabilityStructure;
+  //
+  // For SR-IOV
+  //
   UINT32                                    AriCapabilityOffset;
   UINT32                                    SrIovCapabilityOffset;
   UINT32                                    MrIovCapabilityOffset;
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
index 05c2202..f06b411 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
@@ -2,7 +2,7 @@
 #  The PCI bus driver will probe all PCI devices and allocate MMIO and IO space for these devices.
 #  Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable hot plug supporting.
 #
-#  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -57,6 +57,10 @@
   PciCommand.h
   PciIo.h
   PciBus.h
+  PciFeatureSupport.c
+  PciFeatureSupport.h
+  PciPlatformSupport.c
+  PciPlatformSupport.h
 
 [Packages]
   MdePkg/MdePkg.dec
@@ -91,6 +95,9 @@
   gEfiLoadFile2ProtocolGuid                       ## SOMETIMES_PRODUCES
   gEdkiiIoMmuProtocolGuid                         ## SOMETIMES_CONSUMES
   gEfiLoadedImageDevicePathProtocolGuid           ## CONSUMES
+  gEfiPciExpressPlatformProtocolGuid                     ## SOMETIMES_CONSUMES
+  gEfiPciExpressOverrideProtocolGuid                     ## SOMETIMES_CONSUMES
+
 
 [FeaturePcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport      ## CONSUMES
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
index c7eafff..c9e52ea 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
@@ -1,7 +1,7 @@
 /** @file
   PCI emumeration support functions implementation for PCI Bus module.
 
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -2154,6 +2154,16 @@ CreatePciIoDevice (
              );
   if (!EFI_ERROR (Status)) {
     PciIoDevice->IsPciExp = TRUE;
+    //
+    // read the PCI device's entire PCI Express Capability structure
+    //
+    PciIo->Pci.Read (
+                  PciIo,
+                  EfiPciIoWidthUint8,
+                  PciIoDevice->PciExpressCapabilityOffset,
+                  sizeof (PCI_CAPABILITY_PCIEXP) / sizeof (UINT8),
+                  &PciIoDevice->PciExpressCapabilityStructure
+                  );
   }
 
   if (PcdGetBool (PcdAriSupport)) {
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
new file mode 100644
index 0000000..3980a8e
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -0,0 +1,891 @@
+/** @file
+  PCI standard feature support functions implementation for PCI Bus module..
+
+Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciBus.h"
+#include "PciFeatureSupport.h"
+
+/**
+  Hold the current instance of Root Bridge IO protocol Handle
+**/
+EFI_HANDLE                                  mRootBridgeHandle;
+
+/**
+  A gobal pointer to BRIDGE_DEVICE_NODE buffer to track all the primary physical
+  PCI Root Ports (PCI Controllers) for a given PCI Root Bridge instance while
+  enumerating to configure the PCI features
+**/
+LIST_ENTRY                                  mRootBridgeDeviceList;
+
+/**
+ global list to indicate the supported PCI Express features of this driver, it
+ is expected to be overridden based on the platform request
+**/
+EFI_PCI_EXPRESS_PLATFORM_POLICY             mPciExpressPlatformPolicy = {
+    //
+    // support for PCI Express feature - Max. Payload Size
+    //
+    FALSE,
+    //
+    // support for PCI Express feature - Max. Read Request Size
+    //
+    FALSE,
+    //
+    // support for PCI Express feature - Extended Tag
+    //
+    FALSE,
+    //
+    // support for PCI Express feature - Relax Order
+    //
+    FALSE,
+    //
+    // support for PCI Express feature - No-Snoop
+    //
+    FALSE,
+    //
+    // support for PCI Express feature - ASPM state
+    //
+    FALSE,
+    //
+    // support for PCI Express feature - Common Clock Configuration
+    //
+    FALSE,
+    //
+    // support for PCI Express feature - Extended Sync
+    //
+    FALSE,
+    //
+    // support for PCI Express feature - Atomic Op
+    //
+    FALSE,
+    //
+    // support for PCI Express feature - LTR
+    //
+    FALSE,
+    //
+    // support for PCI Express feature - PTM
+    //
+    FALSE,
+    //
+    // support for PCI Express feature - Completion Timeout
+    //
+    FALSE,
+    //
+    // support for PCI Express feature - Clock Power Management
+    //
+    FALSE,
+    //
+    // support for PCI Express feature - L1 PM Substates
+    //
+    FALSE
+};
+
+//
+// indicates the driver has completed query to platform on the list of supported
+// PCI features to be configured
+//
+BOOLEAN   mPciExpressGetPlatformPolicyComplete = FALSE;
+
+//
+// PCI Express feature initialization phase handle routines
+//
+PCI_EXPRESS_FEATURE_INITIALIZATION_POINT  mPciExpressFeatureInitializationList[] = {
+    //
+    // vacant entry, shall be replaced with actual entry when the PCI Express
+    // feature are added.
+    //
+  { 0, 0, NULL}
+};
+
+/**
+  Routine to serially dispatch the designated the PCI Express feature specific
+  functions defined for each of the configuration phase. The order for each phase
+  would be based entirely on the table mPciExpressFeatureInitializationList.
+
+  @param  PciDevice                       pointer to PCI_IO_DEVICE to identify device
+  @param  PciExFeatureConfigPhase         input configuration phase
+  @param  PciExpressFeatureConfiguration  used pointer to void to accomodate any PCI
+                                          Express feature specific data type
+  @retval EFI_STATUS                      output only from feature specific function
+                                          defined in the table mPciExpressFeatureInitializationList
+**/
+EFI_STATUS
+DispatchPciExpressInitializationFunctions (
+  IN PCI_IO_DEVICE                            *PciDevice,
+  IN PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE  PciExFeatureConfigPhase,
+  IN VOID                                     *PciExpressFeatureConfiguration
+  )
+{
+  UINTN       idx;
+  EFI_STATUS  Status;
+  UINT8       *PciExpressPolicy;
+
+  for (
+      idx = 0, PciExpressPolicy = (UINT8*)&mPciExpressPlatformPolicy
+      ; idx < sizeof (mPciExpressFeatureInitializationList) / sizeof (PCI_EXPRESS_FEATURE_INITIALIZATION_POINT)
+      ; idx++
+      ){
+    if (
+        //
+        // match the configuration phase
+        //
+        mPciExpressFeatureInitializationList[idx].PciExpressFeatureConfigurationPhase == PciExFeatureConfigPhase
+        //
+        // check whether the PCI Express features is enabled
+        //
+        && PciExpressPolicy[mPciExpressFeatureInitializationList[idx].PciExpressFeatureId] == TRUE
+        ) {
+      Status =  mPciExpressFeatureInitializationList[idx].PciExpressFeatureConfigurationRoutine (
+                                                            PciDevice,
+                                                            PciExpressFeatureConfiguration
+                                                            );
+    }
+  }
+  return Status;
+}
+
+/**
+  Main routine to indicate platform selection of any of the other PCI features
+  to be configured by this driver
+
+  @retval TRUE    platform has selected the other PCI features to be configured
+          FALSE   platform has not selected any of the other PCI features
+**/
+BOOLEAN
+CheckPciExpressFeatureList (
+  )
+{
+  UINTN     length;
+  UINT8     *list;
+
+  for (
+      length = 0, list = (UINT8*)&mPciExpressPlatformPolicy
+      ; length < sizeof (EFI_PCI_EXPRESS_PLATFORM_POLICY)
+      ; length++
+      ) {
+    if (list[length]) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+/**
+  helper routine to wipe out the global PCI Express feature list
+**/
+VOID
+NegatePciExpressFeatureList (
+  )
+{
+  UINTN     length;
+  UINT8      *list;
+
+  for (
+      length = 0, list = (UINT8*)&mPciExpressPlatformPolicy
+      ; length < sizeof (EFI_PCI_EXPRESS_PLATFORM_POLICY)
+      ; length++
+      ) {
+    if (list[length]) {
+      list[length] = FALSE;
+    }
+  }
+}
+
+/**
+  Main routine to indicate whether the PCI Express feature initialization is
+  required or not
+
+  @retval TRUE    PCI Express feature initialization required
+          FALSE   PCI Express feature not required
+**/
+BOOLEAN
+IsPciExpressFeatureConfigurationRequired (
+  )
+{
+  EFI_STATUS    Status;
+
+  if (mPciExpressGetPlatformPolicyComplete) {
+    return CheckPciExpressFeatureList ();
+  }
+  //
+  // initialize the PCI Express feature data members
+  //
+  InitializeListHead (&mRootBridgeDeviceList);
+  //
+  // check the platform to configure the PCI Express features
+  //
+  mPciExpressGetPlatformPolicyComplete = TRUE;
+
+  Status = PciExpressPlatformGetPolicy ();
+  if (EFI_ERROR (Status)) {
+    //
+    // fail to obtain the PCI Express feature configuration from platform,
+    // negate the list to avoid any unwanted configuration
+    //
+    NegatePciExpressFeatureList ();
+    return FALSE;
+  }
+  //
+  // PCI Express feature configuration list is ready from platform
+  //
+  return TRUE;
+}
+
+
+/**
+  Indicates whether the set of PCI Express features selected by platform requires
+  extended setup, that has additional resources that would be allocated to align
+  all the devices in the PCI tree, and free the resources later.
+
+  @retval TRUE    PCI Express feature requires extended setup
+          FALSE   PCI Express feature does not require extended setup
+**/
+BOOLEAN
+IsPciExpressFeatureExtendedSetupRequired (
+  )
+{
+  UINTN   idx;
+  UINT8   *PciExpressPolicy;
+  //
+  // return TRUE only for those features which are required to be aligned with
+  // common values among all the devices in the PCI tree
+  //
+  for (
+      idx = 0, PciExpressPolicy = (UINT8*)&mPciExpressPlatformPolicy
+      ; idx < sizeof (mPciExpressFeatureInitializationList) / sizeof (PCI_EXPRESS_FEATURE_INITIALIZATION_POINT)
+      ; idx++
+  ){
+    if (
+        //
+        // match the configuration phase to extended setup phase
+        //
+        mPciExpressFeatureInitializationList[idx].PciExpressFeatureConfigurationPhase == PciExpressFeatureEntendedSetupPhase
+        //
+        // check whether the PCI Express features is enabled
+        //
+        && PciExpressPolicy[mPciExpressFeatureInitializationList[idx].PciExpressFeatureId] == TRUE
+    ) {
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+/**
+ Helper routine to determine the existence of previously enumerated PCI device
+
+ @retval  TRUE  PCI device exist
+          FALSE does not exist
+**/
+BOOLEAN
+DeviceExist (
+  PCI_IO_DEVICE                   *PciDevice
+  )
+{
+  EFI_PCI_IO_PROTOCOL   *PciIoProtocol = &PciDevice->PciIo;
+  UINT16                VendorId = 0xFFFF;
+
+  PciIoProtocol->Pci.Read (
+                      PciIoProtocol,
+                      EfiPciIoWidthUint16,
+                      PCI_VENDOR_ID_OFFSET,
+                      1,
+                      &VendorId
+                      );
+  if (VendorId == 0 || VendorId == 0xFFFF) {
+    return FALSE;
+  } else {
+    return TRUE;
+  }
+}
+
+/**
+  Free up memory alloted for the primary physical PCI Root ports of the PCI Root
+  Bridge instance. Free up all the nodes of type BRIDGE_DEVICE_NODE.
+**/
+VOID
+DestroyRootBridgeDeviceNodes ()
+{
+  LIST_ENTRY                *Link;
+  BRIDGE_DEVICE_NODE        *Temp;
+
+  Link = mRootBridgeDeviceList.ForwardLink;
+  while (Link != NULL && Link != &mRootBridgeDeviceList) {
+    Temp = ROOT_BRIDGE_DEVICE_NODE_FROM_LINK (Link);
+    Link = RemoveEntryList (Link);
+    FreePool (Temp->PciExFeaturesConfigurationTable);
+    FreePool (Temp);
+  }
+}
+
+/**
+  Main routine to determine the child PCI devices of a PCI bridge device
+  and group them under a common internal PCI features Configuration table.
+
+  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
+  @param  PciFeaturesConfigTable          A pointer to a pointer to the
+                                          PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE.
+                                          Returns NULL in case of RCiEP or the PCI
+                                          device does match with any of the physical
+                                          Root ports, or it does not belong to any
+                                          Root port's PCI bus range (not a child)
+
+  @retval EFI_SUCCESS                     able to determine the PCI feature
+                                          configuration table. For RCiEP since
+                                          since it is not prepared.
+          EFI_DEVICE_ERROR                the PCI device has invalid EFI device
+                                          path
+**/
+EFI_STATUS
+GetPciExpressFeaturesConfigurationTable (
+  IN  PCI_IO_DEVICE                             *PciDevice,
+  OUT PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  **PciFeaturesConfigTable
+  )
+{
+  LIST_ENTRY                *Link;
+  BRIDGE_DEVICE_NODE        *Temp;
+  BOOLEAN                   NodeMatch;
+  EFI_DEVICE_PATH_PROTOCOL  *RootPortPath;
+  EFI_DEVICE_PATH_PROTOCOL  *PciDevicePath;
+
+  if (IsListEmpty (&mRootBridgeDeviceList)) {
+    //
+    // no populated PCI primary root ports to parse and match the PCI features
+    // configuration table
+    //
+    *PciFeaturesConfigTable = NULL;
+    return EFI_SUCCESS;
+  }
+
+  //
+  // The PCI features configuration table is not built for RCiEP, return NULL
+  //
+  if (PciDevice->PciExpressCapabilityStructure.Capability.Bits.DevicePortType == \
+      PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT) {
+    *PciFeaturesConfigTable = NULL;
+    return EFI_SUCCESS;
+  }
+
+  if (IsDevicePathEnd (PciDevice->DevicePath)){
+    //
+    // the given PCI device does not have a valid device path
+    //
+    *PciFeaturesConfigTable = NULL;
+    return EFI_DEVICE_ERROR;
+  }
+
+
+  Link = mRootBridgeDeviceList.ForwardLink;
+  do {
+    Temp = ROOT_BRIDGE_DEVICE_NODE_FROM_LINK (Link);
+    RootPortPath = Temp->RootBridgeDevicePath;
+    PciDevicePath = PciDevice->DevicePath;
+    NodeMatch = FALSE;
+    //
+    // match the device path from the list of primary Root Ports with the given
+    // device; the initial nodes matching in sequence indicate that the given PCI
+    // device belongs to that PCI tree from the root port
+    //
+    if (IsDevicePathEnd (RootPortPath)) {
+      //
+      // critical error as no device path available in root
+      //
+      *PciFeaturesConfigTable = NULL;
+      return EFI_DEVICE_ERROR;
+    }
+
+    if (EfiCompareDevicePath (RootPortPath, PciDevicePath)) {
+      //
+      // the given PCI device is the primary root port itself
+      //
+      *PciFeaturesConfigTable = Temp->PciExFeaturesConfigurationTable;
+      return EFI_SUCCESS;
+    }
+    //
+    // check this PCI device belongs to the primary root port of the root bridge
+    // any child PCI device will have the same initial device path nodes  as
+    // its parent root port
+    //
+    while (!IsDevicePathEnd (RootPortPath)){
+
+      if (DevicePathNodeLength (RootPortPath) != DevicePathNodeLength (PciDevicePath)) {
+        //
+        // break to check the next primary root port nodes as does not match
+        //
+        NodeMatch = FALSE;
+        break;
+      }
+      if (CompareMem (RootPortPath, PciDevicePath, DevicePathNodeLength (RootPortPath)) != 0) {
+        //
+        // node does not match, break to check next node
+        //
+        NodeMatch = FALSE;
+        break;
+      }
+      NodeMatch = TRUE;
+      //
+      // advance to next node
+      //
+      RootPortPath = NextDevicePathNode (RootPortPath);
+      PciDevicePath = NextDevicePathNode (PciDevicePath);
+    }
+
+    if (NodeMatch == TRUE) {
+      //
+      // device belongs to primary root port, return its PCI feature configuration
+      // table
+      //
+      *PciFeaturesConfigTable = Temp->PciExFeaturesConfigurationTable;
+      return EFI_SUCCESS;
+    }
+
+    //
+    // advance to next Root port node
+    //
+    Link = Link->ForwardLink;
+  } while (Link != &mRootBridgeDeviceList && Link != NULL);
+  //
+  // the PCI device must be RCiEP, does not belong to any primary root port
+  //
+  *PciFeaturesConfigTable = NULL;
+  return EFI_SUCCESS;
+}
+
+/**
+  helper routine to dump the PCIe Device Port Type
+**/
+VOID
+DumpDevicePortType (
+  IN  UINT8   DevicePortType
+  )
+{
+  switch (DevicePortType){
+    case PCIE_DEVICE_PORT_TYPE_PCIE_ENDPOINT:
+      DEBUG (( DEBUG_INFO, "PCIe endpoint found\n"));
+      break;
+    case PCIE_DEVICE_PORT_TYPE_LEGACY_PCIE_ENDPOINT:
+      DEBUG (( DEBUG_INFO, "legacy PCI endpoint found\n"));
+      break;
+    case PCIE_DEVICE_PORT_TYPE_ROOT_PORT:
+      DEBUG (( DEBUG_INFO, "PCIe Root Port found\n"));
+      break;
+    case PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT:
+      DEBUG (( DEBUG_INFO, "PCI switch upstream port found\n"));
+      break;
+    case PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT:
+      DEBUG (( DEBUG_INFO, "PCI switch downstream port found\n"));
+      break;
+    case PCIE_DEVICE_PORT_TYPE_PCIE_TO_PCI_BRIDGE:
+      DEBUG (( DEBUG_INFO, "PCIe-PCI bridge found\n"));
+      break;
+    case PCIE_DEVICE_PORT_TYPE_PCI_TO_PCIE_BRIDGE:
+      DEBUG (( DEBUG_INFO, "PCI-PCIe bridge found\n"));
+      break;
+    case PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT:
+      DEBUG (( DEBUG_INFO, "RCiEP found\n"));
+      break;
+    case PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_EVENT_COLLECTOR:
+      DEBUG (( DEBUG_INFO, "RC Event Collector found\n"));
+      break;
+  }
+}
+
+/**
+   Setup each PCI device as per the pltaform's device-specific policy, in accordance
+   with PCI Express Base specification.
+
+  @param RootBridge             A pointer to the PCI_IO_DEVICE.
+
+  @retval EFI_SUCCESS           processing each PCI feature as per policy defined
+                                was successful.
+ **/
+EFI_STATUS
+SetupDevicePciExpressFeatures (
+  IN  PCI_IO_DEVICE                           *PciDevice,
+  IN  PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE PciConfigPhase
+  )
+{
+  EFI_STATUS                              Status;
+  PCI_REG_PCIE_CAPABILITY                 PcieCap;
+  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciExpressFeaturesConfigTable;
+
+  PciExpressFeaturesConfigTable = NULL;
+  Status = GetPciExpressFeaturesConfigurationTable (PciDevice, &PciExpressFeaturesConfigTable);
+
+  if (PciConfigPhase == PciExpressFeatureSetupPhase) {
+    DEBUG_CODE (
+      if (EFI_ERROR( Status)) {
+        DEBUG ((
+          DEBUG_WARN,
+          "[Cfg group: 0 {error in dev path}]"
+          ));
+      } else if (PciExpressFeaturesConfigTable == NULL) {
+        DEBUG ((
+          DEBUG_INFO,
+          "[Cfg group: 0]"
+          ));
+      } else {
+        DEBUG ((
+          DEBUG_INFO,
+          "[Cfg group: %d]",
+          PciExpressFeaturesConfigTable->ID
+          ));
+      }
+      PcieCap.Uint16 = PciDevice->PciExpressCapabilityStructure.Capability.Uint16;
+      DumpDevicePortType ((UINT8)PcieCap.Bits.DevicePortType);
+    );
+
+    //
+    // get the device-specific platform policy for the PCI Express features
+    //
+    Status = PciExpressPlatformGetDevicePolicy (PciDevice);
+    if (EFI_ERROR(Status)) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "Error in obtaining PCI device policy!!!\n"
+        ));
+    }
+  }
+
+  DEBUG ((DEBUG_INFO, "["));
+
+  Status = DispatchPciExpressInitializationFunctions (
+            PciDevice,
+            PciConfigPhase,
+            PciExpressFeaturesConfigTable
+            );
+
+  DEBUG ((DEBUG_INFO, "]\n"));
+  return Status;
+}
+
+/**
+  Create and append a node of type BRIDGE_DEVICE_NODE in the list for the primary
+  Root Port so that all its child PCI devices can be identified against the PCI
+  features configuration table group ID, of type PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE.
+
+  @param BridgePort    A pointer to the PCI_IO_DEVICE
+  @param PortNumber    A UINTN value to identify the PCI feature configuration
+                       table group
+
+  @retval EFI_SUCCESS           success in adding a node of BRIDGE_DEVICE_NODE
+                                to the list
+          EFI_OUT_OF_RESOURCES  unable to get memory for creating the node
+**/
+EFI_STATUS
+CreatePciRootBridgeDeviceNode (
+  IN  PCI_IO_DEVICE           *BridgePort,
+  IN  UINTN                   PortNumber
+  )
+{
+  BRIDGE_DEVICE_NODE                        *RootBridgeNode = NULL;
+  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciConfigTable = NULL;
+
+  RootBridgeNode = AllocateZeroPool (sizeof (BRIDGE_DEVICE_NODE));
+  if (RootBridgeNode == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  RootBridgeNode->Signature                     = PCI_ROOT_BRIDGE_DEVICE_SIGNATURE;
+  RootBridgeNode->RootBridgeDevicePath          = BridgePort->DevicePath;
+  PciConfigTable = AllocateZeroPool (
+                     sizeof (PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE)
+                     );
+  if (PciConfigTable) {
+    PciConfigTable->ID                          = PortNumber;
+  }
+
+  RootBridgeNode->PciExFeaturesConfigurationTable  = PciConfigTable;
+
+  InsertTailList (&mRootBridgeDeviceList, &RootBridgeNode->NextRootBridgeDevice);
+
+  if (PciConfigTable == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  return EFI_SUCCESS;
+}
+
+/**
+  Scan all the nodes of the RootBridge to identify and create a separate list
+  of all primary physical PCI root ports and link each with its own instance of
+  the PCI Feature Configuration Table.
+
+  @param  RootBridge    A pointer to the PCI_IO_DEVICE of the PCI Root Bridge
+
+  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store PCI feature
+                                configuration table for all the physical PCI root
+                                ports given
+          EFI_NOT_FOUND         No PCI Bridge device found
+          EFI_SUCCESS           PCI Feature COnfiguration table created for all
+                                the PCI Rooot ports found
+          EFI_INVALID_PARAMETER invalid parameter passed to the routine which
+                                creates the PCI controller node for the primary
+                                Root post list
+**/
+EFI_STATUS
+CreatePciRootBridgeDeviceList (
+  IN  PCI_IO_DEVICE           *RootBridge
+  )
+{
+  EFI_STATUS              Status = EFI_NOT_FOUND;
+  LIST_ENTRY              *Link;
+  PCI_IO_DEVICE           *Device;
+  UINTN                   BridgeDeviceCount;
+
+  BridgeDeviceCount = 0;
+  for ( Link = RootBridge->ChildList.ForwardLink
+      ; Link != &RootBridge->ChildList
+      ; Link = Link->ForwardLink
+  ) {
+    Device = PCI_IO_DEVICE_FROM_LINK (Link);
+    if (!DeviceExist (Device)) {
+      continue;
+    }
+    if (IS_PCI_BRIDGE (&Device->Pci)) {
+      BridgeDeviceCount++;
+      DEBUG ((
+        DEBUG_INFO,
+        "#%d ::Bridge [%02x|%02x|%02x]",
+        BridgeDeviceCount, Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+        ));
+      //
+      // create a list of bridge devices if that is connected to any other device
+      //
+      if (!IsListEmpty (&Device->ChildList)) {
+        DEBUG ((
+          DEBUG_INFO,
+          "- has downstream device!\n"
+          ));
+        Status = CreatePciRootBridgeDeviceNode (Device, BridgeDeviceCount);
+        if (EFI_ERROR (Status)) {
+          DEBUG ((
+            DEBUG_ERROR,
+            "PCI configuration table allocation failure for #%d ::Bridge [%02x|%02x|%02x]\n",
+            BridgeDeviceCount, Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+            ));
+        }
+      } else {
+        DEBUG ((
+          DEBUG_INFO,
+          "- no downstream device!\n"
+          ));
+      }
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Initialize the device's PCI Express features, in a staged manner
+  @param  PciDevice             A pointer to the PCI_IO_DEVICE.
+
+  @retval EFI_SUCCESS           initializing all the nodes of the root bridge
+                                instances were successfull.
+**/
+EFI_STATUS
+InitializeDevicePciExpressFeatures (
+  IN  PCI_IO_DEVICE                           *PciDevice,
+  IN  PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE PciConfigPhase
+  )
+{
+  EFI_STATUS            Status;
+
+  switch (PciConfigPhase) {
+    case PciExpressFeatureSetupPhase:
+    case PciExpressFeatureEntendedSetupPhase:
+    case PciExpressFeatureProgramPhase:
+      Status = SetupDevicePciExpressFeatures (PciDevice, PciConfigPhase);
+      break;
+    case PciExpressFeatureEndPhase:
+      Status = PciExpressPlatformNotifyDeviceState (PciDevice);
+      break;
+  }
+  return Status;
+}
+
+/**
+  Traverse all the nodes from the root bridge or PCI-PCI bridge instance, to
+  configure the PCI Express features as per the PCI Express Base Secification
+  by considering its device-specific platform policy, and its device capability,
+  as applicable.
+
+  @param RootBridge             A pointer to the PCI_IO_DEVICE.
+
+  @retval EFI_SUCCESS           Traversing all the nodes of the root bridge
+                                instances were successfull.
+**/
+EFI_STATUS
+InitializePciExpressFeatures (
+  IN  PCI_IO_DEVICE                           *RootBridge,
+  IN  PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE PciConfigPhase
+  )
+{
+  EFI_STATUS            Status;
+  LIST_ENTRY            *Link;
+  PCI_IO_DEVICE         *Device;
+
+  for ( Link = RootBridge->ChildList.ForwardLink
+      ; Link != &RootBridge->ChildList
+      ; Link = Link->ForwardLink
+  ) {
+    Device = PCI_IO_DEVICE_FROM_LINK (Link);
+    if (!DeviceExist (Device)) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "::Device [%02x|%02x|%02x] - does not exist!!!\n",
+        Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+        ));
+      continue;
+    }
+    if (IS_PCI_BRIDGE (&Device->Pci)) {
+      DEBUG ((
+        DEBUG_INFO,
+        "::Bridge [%02x|%02x|%02x] -",
+        Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+        ));
+      if (Device->IsPciExp) {
+        Status = InitializeDevicePciExpressFeatures (
+                  Device,
+                  PciConfigPhase
+                  );
+      } else {
+        DEBUG ((
+          DEBUG_INFO,
+          "Not a PCIe capable device!\n"
+          ));
+        //
+        // PCI Bridge which does not have PCI Express Capability structure
+        // cannot process this kind of PCI Bridge device
+        //
+      }
+
+      InitializePciExpressFeatures (Device, PciConfigPhase);
+    } else {
+      DEBUG ((
+        DEBUG_INFO,
+        "::Device [%02x|%02x|%02x] -",
+        Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+        ));
+      if (Device->IsPciExp) {
+        Status = InitializeDevicePciExpressFeatures (
+                  Device,
+                  PciConfigPhase
+                  );
+      } else {
+        DEBUG ((
+          DEBUG_INFO,
+          "Not a PCIe capable device!\n"
+          ));
+        //
+        // PCI Device which does not have PCI Express Capability structure
+        // cannot process this kind of PCI device
+        //
+      }
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Enumerate all the nodes of the specified root bridge or PCI-PCI Bridge, to
+  configure the other PCI features.
+
+  @param RootBridge          A pointer to the PCI_IO_DEVICE.
+
+  @retval EFI_SUCCESS           The other PCI features configuration during enumeration
+                                of all the nodes of the PCI root bridge instance were
+                                programmed in PCI-compliance pattern along with the
+                                device-specific policy, as applicable.
+  @retval EFI_UNSUPPORTED       One of the override operation maong the nodes of
+                                the PCI hierarchy resulted in a incompatible address
+                                range.
+  @retval EFI_INVALID_PARAMETER The override operation is performed with invalid input
+                                parameters.
+**/
+EFI_STATUS
+EnumeratePciExpressFeatures (
+  IN EFI_HANDLE             Controller,
+  IN PCI_IO_DEVICE          *RootBridge
+  )
+{
+  EFI_STATUS            Status;
+  UINTN                 PciExpressFeatureConfigPhase;
+
+  if (!IsPciExpressFeatureConfigurationRequired ()) {
+    //
+    // exit as agreement is not reached with platform to configure the PCI
+    // Express features
+    //
+    return EFI_SUCCESS;
+  }
+  mRootBridgeHandle = Controller;
+
+  DEBUG_CODE (
+    CHAR16                *Str;
+    Str = ConvertDevicePathToText (
+            DevicePathFromHandle (RootBridge->Handle),
+            FALSE,
+            FALSE
+            );
+    DEBUG ((
+      DEBUG_INFO,
+      "Enumerating PCI features for Root Bridge %s\n",
+      Str != NULL ? Str : L""
+      ));
+
+    if (Str != NULL) {
+      FreePool (Str);
+    }
+  );
+
+  for ( PciExpressFeatureConfigPhase = PciExpressFeaturePreProcessPhase
+      ; PciExpressFeatureConfigPhase <= PciExpressFeatureEndPhase
+      ; PciExpressFeatureConfigPhase++
+      ) {
+    DEBUG ((
+      DEBUG_INFO,
+      "<<********** Phase [%d]**********>>\n",
+      PciExpressFeatureConfigPhase
+      ));
+    if (PciExpressFeatureConfigPhase == PciExpressFeaturePreProcessPhase) {
+      //
+      // create a list of root bridge devices (root ports) of the root complex
+      // if extra setup phase required
+      //
+      if (IsPciExpressFeatureExtendedSetupRequired ()) {
+        CreatePciRootBridgeDeviceList (RootBridge);
+      }
+      continue;
+    }
+    if (PciExpressFeatureConfigPhase == PciExpressFeatureEntendedSetupPhase) {
+      if (!IsPciExpressFeatureExtendedSetupRequired ()) {
+        //
+        // since the PCI Express features require no extra initialization steps
+        // skip this phase
+        //
+        continue;
+      }
+    }
+    //
+    // setup the PCI Express features
+    //
+    Status = InitializePciExpressFeatures (RootBridge, PciExpressFeatureConfigPhase);
+
+    if (PciExpressFeatureConfigPhase == PciExpressFeatureEndPhase) {
+      //
+      // clean up the temporary resource nodes created for this root bridge
+      //
+      if (IsPciExpressFeatureExtendedSetupRequired ()) {
+        DestroyRootBridgeDeviceNodes ();
+      }
+    }
+  }
+
+  return Status;
+}
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
new file mode 100644
index 0000000..2eff8aa
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
@@ -0,0 +1,226 @@
+/** @file
+  PCI standard feature support functions implementation for PCI Bus module..
+
+Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_PCI_FEATURES_SUPPORT_H_
+#define _EFI_PCI_FEATURES_SUPPORT_H_
+
+extern  EFI_HANDLE                                  mRootBridgeHandle;
+extern  EFI_PCI_EXPRESS_PLATFORM_POLICY             mPciExpressPlatformPolicy;
+//
+// defines the data structure to hold the details of the PCI Root port devices
+//
+typedef struct _BRIDGE_DEVICE_NODE  BRIDGE_DEVICE_NODE;
+
+//
+// defines the data structure to hold the configuration data for the other PCI
+// features
+//
+typedef struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE;
+
+//
+// define the data type for the PCI feature policy support
+//
+typedef struct _PCI_FEATURE_POLICY  PCI_FEATURE_POLICY;
+
+//
+// Signature value for the PCI Root Port node
+//
+#define PCI_ROOT_BRIDGE_DEVICE_SIGNATURE               SIGNATURE_32 ('p', 'c', 'i', 'p')
+
+//
+// Definitions of the PCI Root Port data structure members
+//
+struct _BRIDGE_DEVICE_NODE {
+  //
+  // Signature header
+  //
+  UINT32                                    Signature;
+  //
+  // linked list pointers to next node
+  //
+  LIST_ENTRY                                NextRootBridgeDevice;
+  //
+  // pointer to PCI_IO_DEVICE of the primary PCI Controller device
+  //
+  EFI_DEVICE_PATH_PROTOCOL                  *RootBridgeDevicePath;
+  //
+  // pointer to the corresponding PCI Express feature configuration Table node
+  // all the child PCI devices of the controller are aligned based on this table
+  //
+  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciExFeaturesConfigurationTable;
+};
+
+#define ROOT_BRIDGE_DEVICE_NODE_FROM_LINK(a) \
+  CR (a, BRIDGE_DEVICE_NODE, NextRootBridgeDevice, PCI_ROOT_BRIDGE_DEVICE_SIGNATURE)
+
+//
+// Definition of the PCI Feature configuration Table members
+//
+struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE {
+  //
+  // Configuration Table ID
+  //
+  UINTN                                     ID;
+};
+
+//
+// Declaration of the internal sub-phases during enumeration to configure the PCI
+// Express features
+//
+typedef enum {
+  //
+  // preprocessing applicable only to few PCI Express features to bind all devices
+  // under the common root bridge device (root port), that would be useful to align
+  // all devices with a common value. This would be optional phase based on the
+  // type of the PCI Express feature to be programmed based on platform policy
+  //
+  PciExpressFeaturePreProcessPhase,
+
+  //
+  // mandatory phase to setup the PCI Express feature to its applicable attribute,
+  // based on its device-specific platform policies, matching with its device capabilities
+  //
+  PciExpressFeatureSetupPhase,
+
+  //
+  // optional phase primarily to align all devices, specially required when PCI
+  // switch is present in the hierarchy, applicable to certain few PCI Express
+  // features only
+  //
+  PciExpressFeatureEntendedSetupPhase,
+
+  //
+  // mandatory programming phase to complete the configuration of the PCI Express
+  // features
+  //
+  PciExpressFeatureProgramPhase,
+
+  //
+  // optional phase to clean up temporary buffers, like those that were prepared
+  // during the preprocessing phase above
+  //
+  PciExpressFeatureEndPhase
+
+}PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE;
+
+//
+// declaration for the data type to harbor the PCI feature policies
+//
+struct  _PCI_FEATURE_POLICY {
+  //
+  // if set, it indicates the feature should be enabled
+  // if clear, it indicates the feature should be disabled
+  //
+  UINT8   Act : 1;
+  //
+  // this field will be specific to feature, it can be implementation specific
+  // or it can be reserved and remain unused
+  //
+  UINT8   Support : 6;
+  //
+  // if set indicates override the feature policy defined by the members above
+  // if clear it indicates that this feature policy should be ignored completely
+  // this means the above two members should not be used
+  //
+  UINT8   Override : 1;
+};
+
+//
+// Declaration of the PCI Express features unique Id
+//
+typedef enum {
+  //
+  // support for PCI Express feature - Max. Payload Size
+  //
+  PciExpressMps,
+  //
+  // support for PCI Express feature - Max. Read Request Size
+  //
+  PciExpressMrrs,
+  //
+  // support for PCI Express feature - Extended Tag
+  //
+  PciExpressExtTag,
+  //
+  // support for PCI Express feature - Relax Order
+  //
+  PciExpressRelaxOrder,
+  //
+  // support for PCI Express feature - No-Snoop
+  //
+  PciExpressNoSnoop,
+  //
+  // support for PCI Express feature - ASPM state
+  //
+  PciExpressAspm,
+  //
+  // support for PCI Express feature - Common Clock Configuration
+  //
+  PciExpressCcc,
+  //
+  // support for PCI Express feature - Extended Sync
+  //
+  PciExpressExtSync,
+  //
+  // support for PCI Express feature - Atomic Op
+  //
+  PciExpressAtomicOp,
+  //
+  // support for PCI Express feature - LTR
+  //
+  PciExpressLtr,
+  //
+  // support for PCI Express feature - PTM
+  //
+  PciExpressPtm,
+  //
+  // support for PCI Express feature - Completion Timeout
+  //
+  PciExpressCto,
+  //
+  // support for PCI Express feature - Clock Power Management
+  //
+  PciExpressCpm,
+  //
+  // support for PCI Express feature - L1 PM Substates
+  //
+  PciExpressL1PmSubstates
+
+} PCI_EXPRESS_FEATURE_ID;
+
+//
+// PCI Express feature configuration routine during initialization phases
+//
+typedef
+EFI_STATUS
+(*PCI_EXPRESS_FEATURE_CONFIGURATION_ROUTINE) (
+  IN PCI_IO_DEVICE                            *PciDevice,
+  IN VOID                                     *PciExpressFeatureConfiguration
+  );
+
+//
+// data type for the PCI Express feature initialization phases
+//
+typedef struct {
+  //
+  // Pci Express feature configuration phase
+  //
+  PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE   PciExpressFeatureConfigurationPhase;
+  //
+  // PCI Express feature Id
+  //
+  PCI_EXPRESS_FEATURE_ID                    PciExpressFeatureId;
+  //
+  // PCI Express feature configuration routine
+  //
+  PCI_EXPRESS_FEATURE_CONFIGURATION_ROUTINE PciExpressFeatureConfigurationRoutine;
+
+}PCI_EXPRESS_FEATURE_INITIALIZATION_POINT;
+
+
+#endif
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
new file mode 100644
index 0000000..31c675d
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
@@ -0,0 +1,302 @@
+/** @file
+  This file encapsulate the usage of PCI Platform Protocol
+
+  This file define the necessary hooks used to obtain the platform
+  level data and policies which could be used in the PCI Enumeration phases
+
+Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciBus.h"
+
+
+EFI_PCI_EXPRESS_PLATFORM_PROTOCOL             *mPciExPlatformProtocol;
+EFI_PCI_EXPRESS_OVERRIDE_PROTOCOL             *mPciExOverrideProtocol;
+
+
+/**
+  This function retrieves the PCI Express Platform Protocols published by platform
+  @retval EFI_STATUS          direct return status from the LocateProtocol ()
+                              boot service for the PCI Express Override Protocol
+          EFI_SUCCESS         The PCI Express Platform Protocol is found
+**/
+EFI_STATUS
+GetPciExpressProtocol (
+  )
+{
+  EFI_STATUS  Status;
+
+  if (mPciExPlatformProtocol) {
+    //
+    // the PCI Express Platform Protocol is already initialized
+    //
+    return EFI_SUCCESS;
+  }
+  if (mPciExOverrideProtocol) {
+    //
+    // the PCI Express Override Protocol is already initialized
+    //
+    return EFI_SUCCESS;
+  }
+  //
+  // locate the PCI Express Platform Protocol
+  //
+  Status = gBS->LocateProtocol (
+                  &gEfiPciExpressPlatformProtocolGuid,
+                  NULL,
+                  (VOID **) &mPciExPlatformProtocol
+                  );
+  if (!EFI_ERROR (Status)) {
+    return Status;
+  }
+  //
+  // If PCI Express Platform protocol doesn't exist, try to get the Pci Express
+  // Override Protocol.
+  //
+  return gBS->LocateProtocol (
+                &gEfiPciExpressOverrideProtocolGuid,
+                NULL,
+                (VOID **) &mPciExOverrideProtocol
+                );
+}
+
+/**
+  This function indicates that the platform has published the PCI Express Platform
+  Protocol (or PCI Express Override Protocol) to indicate that this driver can
+  initialize the PCI Express features.
+  @retval     TRUE or FALSE
+**/
+BOOLEAN
+IsPciExpressProtocolPresent (
+  )
+{
+  if (
+      mPciExPlatformProtocol == NULL
+      && mPciExOverrideProtocol == NULL
+      ) {
+    return FALSE;
+  }
+  return TRUE;
+}
+
+
+/**
+  Generic routine to setup the PCI features as per its predetermined defaults.
+**/
+VOID
+SetupDefaultPciExpressDevicePolicy (
+  IN  PCI_IO_DEVICE               *PciDevice
+  )
+{
+
+}
+
+/**
+  initialize the device policy data members
+**/
+VOID
+InitializeDevicePolicyData (
+  IN EFI_PCI_EXPRESS_DEVICE_POLICY  *PciExpressDevicePolicy
+  )
+{
+  UINTN     length;
+  UINT8     *PciExpressPolicy;
+  UINT8     *PciExDevicePolicy;
+
+
+  ZeroMem (PciExpressDevicePolicy, sizeof (EFI_PCI_EXPRESS_DEVICE_POLICY));
+
+  for (
+      length = 0
+      , PciExpressPolicy = (UINT8*)&mPciExpressPlatformPolicy
+      , PciExDevicePolicy = (UINT8*)PciExpressDevicePolicy
+      ; length < sizeof (EFI_PCI_EXPRESS_PLATFORM_POLICY)
+      ; length++
+      ) {
+    if (!PciExpressPolicy[length]) {
+      PciExDevicePolicy[length] = EFI_PCI_EXPRESS_NOT_APPLICABLE;
+    }
+  }
+}
+
+/**
+  Intermediate routine to either get the PCI device specific platform policies
+  through the PCI Platform Protocol, or its alias the PCI Override Protocol.
+
+  @param  PciDevice           A pointer to PCI_IO_DEVICE
+  @param  PciPlatformProtocol A pointer to EFI_PCI_EXPRESS_PLATFORM_PROTOCOL
+
+  @retval EFI_STATUS          The direct status from the PCI Platform Protocol
+  @retval EFI_SUCCESS         if on returning predetermined PCI features defaults,
+                              for the case when protocol returns as EFI_UNSUPPORTED
+                              to indicate PCI device exist and it has no platform
+                              policy defined.
+**/
+EFI_STATUS
+GetPciExpressDevicePolicy (
+  IN  PCI_IO_DEVICE                     *PciDevice,
+  IN  EFI_PCI_EXPRESS_PLATFORM_PROTOCOL *PciPlatformProtocol
+  )
+{
+  EFI_PCI_EXPRESS_DEVICE_POLICY               PciExpressDevicePolicy;
+  EFI_STATUS                                  Status;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;
+
+  PciAddress.Bus = PciDevice->BusNumber;
+  PciAddress.Device = PciDevice->DeviceNumber;
+  PciAddress.Function = PciDevice->FunctionNumber;
+  PciAddress.Register = 0;
+  PciAddress.ExtendedRegister = 0;
+
+  InitializeDevicePolicyData (&PciExpressDevicePolicy);
+  Status = PciPlatformProtocol->GetDevicePolicy (
+                                  PciPlatformProtocol,
+                                  mRootBridgeHandle,
+                                  PciAddress,
+                                  sizeof (EFI_PCI_EXPRESS_DEVICE_POLICY),
+                                  &PciExpressDevicePolicy
+                                  );
+  if (!EFI_ERROR(Status)) {
+    //
+    // platform chipset policies are returned for this PCI device
+    //
+
+
+    DEBUG ((
+      DEBUG_INFO,
+      "[device policy: platform]"
+      ));
+    return Status;
+  } else if (Status == EFI_UNSUPPORTED) {
+    //
+    // platform chipset policies are not provided for this PCI device
+    // let the enumeration happen as per the PCI standard way
+    //
+    SetupDefaultPciExpressDevicePolicy (PciDevice);
+    DEBUG ((
+      DEBUG_INFO,
+      "[device policy: default]"
+      ));
+    return EFI_SUCCESS;
+  }
+  DEBUG ((
+    DEBUG_ERROR,
+    "[device policy: none (error)]"
+    ));
+  return Status;
+}
+
+/**
+  Gets the PCI device-specific platform policy from the PCI Express Platform Protocol.
+  If no PCI Platform protocol is published than setup the PCI feature to predetermined
+  defaults, in order to align all the PCI devices in the PCI hierarchy, as applicable.
+
+  @param  PciDevice     A pointer to PCI_IO_DEVICE
+
+  @retval EFI_STATUS    The direct status from the PCI Platform Protocol
+  @retval EFI_SUCCESS   On return of predetermined PCI features defaults, for
+                        the case when protocol returns as EFI_UNSUPPORTED to
+                        indicate PCI device exist and it has no platform policy
+                        defined. Also, on returns when no PCI Platform Protocol
+                        exist.
+**/
+EFI_STATUS
+PciExpressPlatformGetDevicePolicy (
+  IN PCI_IO_DEVICE          *PciDevice
+  )
+{
+  if (mPciExPlatformProtocol != NULL) {
+    return GetPciExpressDevicePolicy (PciDevice, mPciExPlatformProtocol);
+  } else if (mPciExOverrideProtocol != NULL) {
+    return GetPciExpressDevicePolicy (PciDevice, mPciExOverrideProtocol);
+  } else {
+    //
+    // no protocol found, platform does not require the PCI Express initialization
+    //
+    return EFI_UNSUPPORTED;
+  }
+}
+
+/**
+  This function gets the platform requirement to initialize the list of PCI Express
+  features from the protocol definition supported.
+  This function should be called after the LocatePciPlatformProtocol.
+  @retval EFI_SUCCESS           return by platform to acknowledge the list of
+                                PCI Express feature to be configured
+                                (in mPciExpressPlatformPolicy)
+          EFI_INVALID_PARAMETER platform does not support the protocol arguements
+                                passed
+          EFI_UNSUPPORTED       platform did not published the protocol
+**/
+EFI_STATUS
+PciExpressPlatformGetPolicy (
+  )
+{
+  EFI_STATUS    Status;
+
+  if (mPciExPlatformProtocol) {
+    Status = mPciExPlatformProtocol->GetPolicy (
+                                      mPciExPlatformProtocol,
+                                      sizeof (EFI_PCI_EXPRESS_PLATFORM_POLICY),
+                                      &mPciExpressPlatformPolicy
+                                      );
+  } else if (mPciExOverrideProtocol) {
+    Status = mPciExOverrideProtocol->GetPolicy (
+                                      mPciExOverrideProtocol,
+                                      sizeof (EFI_PCI_EXPRESS_PLATFORM_POLICY),
+                                      &mPciExpressPlatformPolicy
+                                      );
+  } else {
+    //
+    // no protocol found, platform does not require the PCI Express initialization
+    //
+    return EFI_UNSUPPORTED;
+  }
+  return Status;
+}
+
+
+/**
+  Notifies the platform about the current PCI Express state of the device.
+
+  @param  PciDevice                 A pointer to PCI_IO_DEVICE
+  @param  PciExDeviceConfiguration  Pointer to EFI_PCI_EXPRESS_DEVICE_CONFIGURATION.
+                                    Used to pass the current state of device to
+                                    platform.
+
+  @retval EFI_STATUS        The direct status from the PCI Express Platform Protocol
+  @retval EFI_UNSUPPORTED   returns when the PCI Express Platform Protocol or its
+                            alias PCI Express OVerride Protocol is not present.
+**/
+EFI_STATUS
+PciExpressPlatformNotifyDeviceState (
+  IN PCI_IO_DEVICE                        *PciDevice
+  )
+{
+  EFI_PCI_EXPRESS_DEVICE_CONFIGURATION      PciExDeviceConfiguration;
+
+
+  if (mPciExPlatformProtocol != NULL) {
+    return mPciExPlatformProtocol->NotifyDeviceState (
+                                    mPciExPlatformProtocol,
+                                    PciDevice->Handle,
+                                    sizeof (EFI_PCI_EXPRESS_DEVICE_CONFIGURATION),
+                                    &PciExDeviceConfiguration
+                                    );
+  } else if (mPciExOverrideProtocol != NULL) {
+    return mPciExOverrideProtocol->NotifyDeviceState (
+                                    mPciExOverrideProtocol,
+                                    PciDevice->Handle,
+                                    sizeof (EFI_PCI_EXPRESS_DEVICE_CONFIGURATION),
+                                    &PciExDeviceConfiguration
+                                    );
+  } else {
+    //
+    // unexpected error
+    //
+    return EFI_UNSUPPORTED;
+  }
+}
+
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
new file mode 100644
index 0000000..4283b81
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
@@ -0,0 +1,87 @@
+/** @file
+  This file encapsulate the usage of PCI Platform Protocol
+
+  This file define the necessary hooks used to obtain the platform
+  level data and policies which could be used in the PCI Enumeration phases
+
+Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#ifndef _EFI_PCI_PLATFORM_SUPPORT_H_
+#define _EFI_PCI_PLATFORM_SUPPORT_H_
+
+
+/**
+  This function retrieves the PCI Express Platform Protocols published by platform
+  @retval EFI_STATUS          direct return status from the LocateProtocol ()
+                              boot service for the PCI Express Override Protocol
+          EFI_SUCCESS         The PCI Express Platform Protocol is found
+**/
+EFI_STATUS
+GetPciExpressProtocol (
+  );
+
+/**
+  This function indicates that the platform has published the PCI Express Platform
+  Protocol (or PCI Express Override Protocol) to indicate that this driver can
+  initialize the PCI Express features.
+  @retval     TRUE or FALSE
+**/
+BOOLEAN
+IsPciExpressProtocolPresent (
+  );
+
+/**
+  This function gets the platform requirement to initialize the list of PCI Express
+  features from the protocol definition supported.
+  This function should be called after the LocatePciPlatformProtocol.
+  @retval EFI_SUCCESS           return by platform to acknowledge the list of
+                                PCI Express feature to be configured
+                                (in mPciExpressPlatformPolicy)
+          EFI_INVALID_PARAMETER platform does not support the protocol arguements
+                                passed
+          EFI_UNSUPPORTED       platform did not published the protocol
+**/
+EFI_STATUS
+PciExpressPlatformGetPolicy (
+  );
+
+/**
+  Gets the PCI device-specific platform policy from the PCI Platform Protocol.
+  If no PCI Platform protocol is published than setup the PCI feature to predetermined
+  defaults, in order to align all the PCI devices in the PCI hierarchy, as applicable.
+
+  @param  PciDevice     A pointer to PCI_IO_DEVICE
+
+  @retval EFI_STATUS    The direct status from the PCI Platform Protocol
+  @retval EFI_SUCCESS   On return of predetermined PCI features defaults, for
+                        the case when protocol returns as EFI_UNSUPPORTED to
+                        indicate PCI device exist and it has no platform policy
+                        defined. Also, on returns when no PCI Platform Protocol
+                        exist.
+**/
+EFI_STATUS
+PciExpressPlatformGetDevicePolicy (
+  IN PCI_IO_DEVICE          *PciDevice
+  );
+
+/**
+  Notifies the platform about the current PCI Express state of the device.
+
+  @param  PciDevice                 A pointer to PCI_IO_DEVICE
+  @param  PciExDeviceConfiguration  Pointer to EFI_PCI_EXPRESS_DEVICE_CONFIGURATION.
+                                    Used to pass the current state of device to
+                                    platform.
+
+  @retval EFI_STATUS        The direct status from the PCI Express Platform Protocol
+  @retval EFI_UNSUPPORTED   returns when the PCI Express Platform Protocol or its
+                            alias PCI Express OVerride Protocol is not present.
+**/
+EFI_STATUS
+PciExpressPlatformNotifyDeviceState (
+  IN PCI_IO_DEVICE                        *PciDevice
+  );
+#endif
-- 
2.21.0.windows.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12] MdeModulePkg/PciBusDxe: Setup PCI Express init phase
  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 ` 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
                   ` (22 subsequent siblings)
  24 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:04 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

References:-
  https://bugzilla.tianocore.org/show_bug.cgi?id=1954
  https://bugzilla.tianocore.org/show_bug.cgi?id=2194
  https://bugzilla.tianocore.org/show_bug.cgi?id=2313
  https://bugzilla.tianocore.org/show_bug.cgi?id=2499
  https://bugzilla.tianocore.org/show_bug.cgi?id=2500

This code change represents the preparation of phase for initializing
the PCI Express features at the end of PCI enumeration phase.

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/PciDeviceSupport.c  | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h |  23 +++++++++++++++++++++++
 2 files changed, 169 insertions(+), 35 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
index b7832c6..07ee9ba 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
@@ -1,7 +1,7 @@
 /** @file
   Supporting functions implementation for PCI devices management.
 
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
 (C) Copyright 2018 Hewlett Packard Enterprise Development LP<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -597,7 +597,7 @@ DeRegisterPciDevice (
 }
 
 /**
-  Start to manage the PCI device on the specified root bridge or PCI-PCI Bridge.
+  Start the PCI root Ports or PCI-PCI Bridge only.
 
   @param Controller          The root bridge handle.
   @param RootBridge          A pointer to the PCI_IO_DEVICE.
@@ -612,7 +612,82 @@ DeRegisterPciDevice (
 
 **/
 EFI_STATUS
-StartPciDevicesOnBridge (
+EnablePciBridges (
+  IN EFI_HANDLE                          Controller,
+  IN PCI_IO_DEVICE                       *RootBridge
+  )
+
+{
+  PCI_IO_DEVICE             *PciIoDevice;
+  EFI_STATUS                Status;
+  LIST_ENTRY                *CurrentLink;
+  UINT64                    Supports;
+
+  PciIoDevice = NULL;
+  CurrentLink = RootBridge->ChildList.ForwardLink;
+
+  while (CurrentLink != NULL && CurrentLink != &RootBridge->ChildList) {
+
+    PciIoDevice = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+    //
+    // check if the device has been assigned with required resource
+    // and registered
+    //
+    if (!PciIoDevice->Registered && !PciIoDevice->Allocated) {
+      return EFI_NOT_READY;
+    }
+
+    if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
+      Status = EnablePciBridges (
+                 Controller,
+                 PciIoDevice
+                 );
+
+      PciIoDevice->PciIo.Attributes (
+                           &(PciIoDevice->PciIo),
+                           EfiPciIoAttributeOperationSupported,
+                           0,
+                           &Supports
+                         );
+      Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
+      PciIoDevice->PciIo.Attributes (
+                           &(PciIoDevice->PciIo),
+                           EfiPciIoAttributeOperationEnable,
+                           Supports,
+                           NULL
+                         );
+
+    }
+
+    CurrentLink = CurrentLink->ForwardLink;
+  }
+
+  if (PciIoDevice == NULL) {
+    return EFI_NOT_FOUND;
+  } else {
+    return EFI_SUCCESS;
+  }
+}
+
+
+/**
+  Register to manage the PCI device on the specified root bridge or PCI-PCI Bridge.
+
+  @param Controller          The root bridge handle.
+  @param RootBridge          A pointer to the PCI_IO_DEVICE.
+  @param RemainingDevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL.
+  @param NumberOfChildren    Children number.
+  @param ChildHandleBuffer   A pointer to the child handle buffer.
+
+  @retval EFI_NOT_READY   Device is not allocated.
+  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
+  @retval EFI_NOT_FOUND   Can not find the specific device.
+  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
+
+**/
+EFI_STATUS
+RegisterPciDevicesOnBridge (
   IN EFI_HANDLE                          Controller,
   IN PCI_IO_DEVICE                       *RootBridge,
   IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
@@ -626,7 +701,6 @@ StartPciDevicesOnBridge (
   EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;
   EFI_STATUS                Status;
   LIST_ENTRY                *CurrentLink;
-  UINT64                    Supports;
 
   PciIoDevice = NULL;
   CurrentLink = RootBridge->ChildList.ForwardLink;
@@ -681,7 +755,7 @@ StartPciDevicesOnBridge (
       // If it is a PPB
       //
       if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
-        Status = StartPciDevicesOnBridge (
+        Status = RegisterPciDevicesOnBridge (
                    Controller,
                    PciIoDevice,
                    CurrentDevicePath,
@@ -689,20 +763,6 @@ StartPciDevicesOnBridge (
                    ChildHandleBuffer
                    );
 
-        PciIoDevice->PciIo.Attributes (
-                             &(PciIoDevice->PciIo),
-                             EfiPciIoAttributeOperationSupported,
-                             0,
-                             &Supports
-                             );
-        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
-        PciIoDevice->PciIo.Attributes (
-                             &(PciIoDevice->PciIo),
-                             EfiPciIoAttributeOperationEnable,
-                             Supports,
-                             NULL
-                             );
-
         return Status;
       } else {
 
@@ -733,28 +793,13 @@ StartPciDevicesOnBridge (
       }
 
       if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
-        Status = StartPciDevicesOnBridge (
+        Status = RegisterPciDevicesOnBridge (
                    Controller,
                    PciIoDevice,
                    RemainingDevicePath,
                    NumberOfChildren,
                    ChildHandleBuffer
                    );
-
-        PciIoDevice->PciIo.Attributes (
-                             &(PciIoDevice->PciIo),
-                             EfiPciIoAttributeOperationSupported,
-                             0,
-                             &Supports
-                             );
-        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
-        PciIoDevice->PciIo.Attributes (
-                             &(PciIoDevice->PciIo),
-                             EfiPciIoAttributeOperationEnable,
-                             Supports,
-                             NULL
-                             );
-
       }
 
       CurrentLink = CurrentLink->ForwardLink;
@@ -768,6 +813,72 @@ StartPciDevicesOnBridge (
   }
 }
 
+/**
+  Start to manage the PCI device on the specified root bridge or PCI-PCI Bridge.
+
+  @param Controller          The root bridge handle.
+  @param RootBridge          A pointer to the PCI_IO_DEVICE.
+  @param RemainingDevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL.
+  @param NumberOfChildren    Children number.
+  @param ChildHandleBuffer   A pointer to the child handle buffer.
+
+  @retval EFI_NOT_READY   Device is not allocated.
+  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
+  @retval EFI_NOT_FOUND   Can not find the specific device.
+  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
+
+**/
+EFI_STATUS
+StartPciDevicesOnBridge (
+  IN EFI_HANDLE                          Controller,
+  IN PCI_IO_DEVICE                       *RootBridge,
+  IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
+  IN OUT UINT8                           *NumberOfChildren,
+  IN OUT EFI_HANDLE                      *ChildHandleBuffer
+  )
+
+{
+  EFI_STATUS                Status;
+
+  //
+  // first register all the PCI devices
+  //
+  Status = RegisterPciDevicesOnBridge (
+             Controller,
+             RootBridge,
+             RemainingDevicePath,
+             NumberOfChildren,
+             ChildHandleBuffer
+             );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  } else {
+    //
+    // the late configuration of PCI Express features
+    // the platform is required to indicate its requirement for the initialization
+    // of PCI Express features by publishing its protocol
+    //
+    if (
+        gFullEnumeration
+        && IsPciExpressProtocolPresent ()
+    ) {
+
+      Status = EnumeratePciExpressFeatures (
+                Controller,
+                RootBridge
+                );
+    }
+    //
+    // finally start those PCI bridge port devices only
+    //
+    return EnablePciBridges (
+             Controller,
+             RootBridge
+             );
+  }
+}
+
 /**
   Start to manage all the PCI devices it found previously under
   the entire host bridge.
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
index 2eff8aa..9b7e51f 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
@@ -223,4 +223,27 @@ typedef struct {
 }PCI_EXPRESS_FEATURE_INITIALIZATION_POINT;
 
 
+
+/**
+  Enumerate all the nodes of the specified root bridge or PCI-PCI Bridge, to
+  configure the other PCI features.
+
+  @param RootBridge          A pointer to the PCI_IO_DEVICE.
+
+  @retval EFI_SUCCESS           The other PCI features configuration during enumeration
+                                of all the nodes of the PCI root bridge instance were
+                                programmed in PCI-compliance pattern along with the
+                                device-specific policy, as applicable.
+  @retval EFI_UNSUPPORTED       One of the override operation maong the nodes of
+                                the PCI hierarchy resulted in a incompatible address
+                                range.
+  @retval EFI_INVALID_PARAMETER The override operation is performed with invalid input
+                                parameters.
+**/
+EFI_STATUS
+EnumeratePciExpressFeatures (
+  IN EFI_HANDLE             Controller,
+  IN PCI_IO_DEVICE          *RootBridge
+  );
+
 #endif
-- 
2.21.0.windows.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12] PciBusDxe: New PCI Express feature Max_Payload_Size
  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 ` 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
                   ` (21 subsequent siblings)
  24 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:04 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2194

The code changes are made to enable the configuration of new PCI Express
feature Max_Payload_Size (MPS), which defines the data packet size for
the PCI transactions, as per the PCI Base Specification 4 Revision 1.

The code changes are made to calibrate highest common value that is appl-
icable to all the child nodes originating from the primary root bridge
device instance.

This programming of MPS is based on each PCI device's capability, and also
its device-specific platform policy obtained using the new PCI Express
Platform Protocol interface, defined in the below feature request:-
https://bugzilla.tianocore.org/show_bug.cgi?id=1954

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/PciBusDxe.inf        |   2 ++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h |  55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  |  22 ++++++++++++++++------
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h  |   5 +++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c |  80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h |  17 +++++++++++++++++
 8 files changed, 369 insertions(+), 6 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index 225229d..5dc5f61 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -287,6 +287,7 @@ struct _PCI_IO_DEVICE {
   // This field is used to support this case.
   //
   UINT16                                    BridgeIoAlignment;
+  UINT8                                     SetupMPS;
 };
 
 #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
index f06b411..e3ad105 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
@@ -61,6 +61,8 @@
   PciFeatureSupport.h
   PciPlatformSupport.c
   PciPlatformSupport.h
+  PciExpressFeatures.c
+  PciExpressFeatures.h
 
 [Packages]
   MdePkg/MdePkg.dec
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
new file mode 100644
index 0000000..6084446
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
@@ -0,0 +1,193 @@
+/** @file
+  PCI standard feature support functions implementation for PCI Bus module..
+
+Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciBus.h"
+#include "PciFeatureSupport.h"
+
+VOID
+ReportPciWriteError (
+  IN UINT8  Bus,
+  IN UINT8  Device,
+  IN UINT8  Function,
+  IN UINT32 Offset
+  )
+{
+  DEBUG ((
+    DEBUG_ERROR,
+    "Unexpected PCI register (%d,%d,%d,0x%x) write error!",
+    Bus,
+    Device,
+    Function,
+    Offset
+    ));
+}
+
+/**
+  Compare and Swap the payload value - between the global variable to maaintain
+  common value among all the devices in the PCIe heirarchy from the root bridge
+  device and all its child devices; with the device-sepcific setup value.
+
+  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
+  @param PciExpressConfigurationTable  pointer to PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
+
+  @retval EFI_SUCCESS                   processing of PCI feature Max_Payload_Size
+                                        is successful.
+**/
+EFI_STATUS
+CasMaxPayloadSize (
+    IN  PCI_IO_DEVICE                             *PciDevice,
+    IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciExpressConfigurationTable
+  )
+{
+  UINT8                                   MpsValue;
+
+  //
+  // align the MPS of the tree to the HCF with this device
+  //
+  if (PciExpressConfigurationTable) {
+    MpsValue = PciExpressConfigurationTable->Max_Payload_Size;
+
+    MpsValue = MIN (PciDevice->SetupMPS, MpsValue);
+    PciDevice->SetupMPS = MIN (PciDevice->SetupMPS, MpsValue);
+
+    if (MpsValue != PciExpressConfigurationTable->Max_Payload_Size) {
+      PciExpressConfigurationTable->Max_Payload_Size = MpsValue;
+    }
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "MPS: %d [DevCap:%d],",
+    PciDevice->SetupMPS, PciDevice->PciExpressCapabilityStructure.DeviceCapability.Bits.MaxPayloadSize
+  ));
+
+  return EFI_SUCCESS;
+}
+
+/**
+  The main routine which process the PCI feature Max_Payload_Size as per the
+  device-specific platform policy, as well as in complaince with the PCI Base
+  specification Revision 4, that aligns the value for the entire PCI heirarchy
+  starting from its physical PCI Root port / Bridge device.
+
+  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
+  @param PciExpressConfigurationTable  pointer to PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
+
+  @retval EFI_SUCCESS                   processing of PCI feature Max_Payload_Size
+                                        is successful.
+**/
+EFI_STATUS
+SetupMaxPayloadSize (
+  IN  PCI_IO_DEVICE                             *PciDevice,
+  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciExpressConfigurationTable
+  )
+{
+  PCI_REG_PCIE_DEVICE_CAPABILITY          PciDeviceCap;
+  UINT8                                   MpsValue;
+
+
+  PciDeviceCap.Uint32 = PciDevice->PciExpressCapabilityStructure.DeviceCapability.Uint32;
+
+  if (PciDevice->SetupMPS == EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_AUTO) {
+    //
+    // configure this feature as per its PCIe device capabilities
+    //
+    MpsValue = (UINT8)PciDeviceCap.Bits.MaxPayloadSize;
+    //
+    // no change to PCI Root ports without any endpoint device
+    //
+    if (IS_PCI_BRIDGE (&PciDevice->Pci) && PciDeviceCap.Bits.MaxPayloadSize) {
+      if (IsListEmpty  (&PciDevice->ChildList)) {
+        //
+        // No device on root bridge
+        //
+        MpsValue = PCIE_MAX_PAYLOAD_SIZE_128B;
+      }
+    }
+  } else {
+    MpsValue = SetDevicePolicyPciExpressMps (PciDevice->SetupMPS);
+  }
+  //
+  // discard device policy override request if greater than PCI device capability
+  //
+  PciDevice->SetupMPS = MIN ((UINT8)PciDeviceCap.Bits.MaxPayloadSize, MpsValue);
+
+  return CasMaxPayloadSize (
+          PciDevice,
+          PciExpressConfigurationTable
+          );
+}
+
+/**
+  Overrides the PCI Device Control register MaxPayloadSize register field; 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
+ProgramMaxPayloadSize (
+  IN PCI_IO_DEVICE          *PciDevice,
+  IN VOID                   *PciExFeatureConfiguration
+  )
+{
+  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
+  UINT32                      Offset;
+  EFI_STATUS                  Status;
+  EFI_TPL                     OldTpl;
+
+  PcieDev.Uint16 = 0;
+  Offset = PciDevice->PciExpressCapabilityOffset +
+               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint16,
+                                  Offset,
+                                  1,
+                                  &PcieDev.Uint16
+                                  );
+  ASSERT (Status == EFI_SUCCESS);
+
+  if (PcieDev.Bits.MaxPayloadSize != PciDevice->SetupMPS) {
+    PcieDev.Bits.MaxPayloadSize = PciDevice->SetupMPS;
+    DEBUG (( DEBUG_INFO, "MPS=%d,", PciDevice->SetupMPS));
+
+    //
+    // 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,
+                                    &PcieDev.Uint16
+                                    );
+    //
+    // Restore TPL to its original level
+    //
+    gBS->RestoreTPL (OldTpl);
+
+    if (!EFI_ERROR(Status)) {
+      PciDevice->PciExpressCapabilityStructure.DeviceControl.Uint16 = PcieDev.Uint16;
+    } else {
+      ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, Offset);
+    }
+  } else {
+    DEBUG (( DEBUG_INFO, "No MPS=%d,", PciDevice->SetupMPS));
+  }
+
+  return Status;
+}
+
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
new file mode 100644
index 0000000..460437b
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
@@ -0,0 +1,55 @@
+/** @file
+  PCI standard feature support functions implementation for PCI Bus module..
+
+Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_PCI_EXPRESS_FEATURES_H_
+#define _EFI_PCI_EXPRESS_FEATURES_H_
+
+
+/**
+  The main routine which process the PCI feature Max_Payload_Size as per the
+  device-specific platform policy, as well as in complaince with the PCI Base
+  specification Revision 4, that aligns the value for the entire PCI heirarchy
+  starting from its physical PCI Root port / Bridge device.
+
+  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
+  @param PciFeaturesConfigurationTable  pointer to PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
+
+  @retval EFI_SUCCESS                   processing of PCI feature Max_Payload_Size
+                                        is successful.
+**/
+EFI_STATUS
+SetupMaxPayloadSize (
+  IN  PCI_IO_DEVICE                             *PciDevice,
+  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciFeaturesConfigurationTable
+  );
+
+EFI_STATUS
+CasMaxPayloadSize (
+  IN  PCI_IO_DEVICE                             *PciDevice,
+  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciFeaturesConfigurationTable
+  );
+
+/**
+  Overrides the PCI Device Control register Max_Read_Req_Size register field; 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 controller.
+  @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
+ProgramMaxPayloadSize (
+  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 3980a8e..aae6139 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -8,6 +8,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 
 #include "PciBus.h"
 #include "PciFeatureSupport.h"
+#include "PciExpressFeatures.h"
 
 /**
   Hold the current instance of Root Bridge IO protocol Handle
@@ -29,7 +30,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY             mPciExpressPlatformPolicy = {
     //
     // support for PCI Express feature - Max. Payload Size
     //
-    FALSE,
+    TRUE,
     //
     // support for PCI Express feature - Max. Read Request Size
     //
@@ -94,11 +95,16 @@ BOOLEAN   mPciExpressGetPlatformPolicyComplete = FALSE;
 // PCI Express feature initialization phase handle routines
 //
 PCI_EXPRESS_FEATURE_INITIALIZATION_POINT  mPciExpressFeatureInitializationList[] = {
-    //
-    // vacant entry, shall be replaced with actual entry when the PCI Express
-    // feature are added.
-    //
-  { 0, 0, NULL}
+
+  {
+    PciExpressFeatureSetupPhase,          PciExpressMps,        SetupMaxPayloadSize
+  },
+  {
+    PciExpressFeatureEntendedSetupPhase,  PciExpressMps,        CasMaxPayloadSize
+  },
+  {
+    PciExpressFeatureProgramPhase,        PciExpressMps,        ProgramMaxPayloadSize
+  }
 };
 
 /**
@@ -597,6 +603,10 @@ CreatePciRootBridgeDeviceNode (
                      );
   if (PciConfigTable) {
     PciConfigTable->ID                          = PortNumber;
+    //
+    // start by assuming 4096B as the default value for the Max. Payload Size
+    //
+    PciConfigTable->Max_Payload_Size            = PCIE_MAX_PAYLOAD_SIZE_4096B;
   }
 
   RootBridgeNode->PciExFeaturesConfigurationTable  = PciConfigTable;
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
index 9b7e51f..4ecbefc 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
@@ -66,6 +66,11 @@ struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE {
   // Configuration Table ID
   //
   UINTN                                     ID;
+  //
+  // to configure the PCI feature Maximum payload size to maintain the data packet
+  // size among all the PCI devices in the PCI hierarchy
+  //
+  UINT8                                     Max_Payload_Size;
 };
 
 //
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
index 31c675d..3e9d4c5 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
@@ -81,6 +81,39 @@ IsPciExpressProtocolPresent (
   return TRUE;
 }
 
+/**
+  Routine to translate the given device-specific platform policy from type
+  EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE to HW-specific value, as per PCI Base Specification
+  Revision 4.0; for the PCI feature Max_Payload_Size.
+
+  @param  MPS     Input device-specific policy should be in terms of type
+                  EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE
+
+  @retval         Range values for the Max_Payload_Size as defined in the PCI
+                  Base Specification 4.0
+**/
+UINT8
+SetDevicePolicyPciExpressMps (
+  IN  UINT8                   MPS
+)
+{
+  switch (MPS) {
+    case EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_128B:
+      return PCIE_MAX_PAYLOAD_SIZE_128B;
+    case EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_256B:
+      return PCIE_MAX_PAYLOAD_SIZE_256B;
+    case EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_512B:
+      return PCIE_MAX_PAYLOAD_SIZE_512B;
+    case EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_1024B:
+      return PCIE_MAX_PAYLOAD_SIZE_1024B;
+    case EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_2048B:
+      return PCIE_MAX_PAYLOAD_SIZE_2048B;
+    case EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_4096B:
+      return PCIE_MAX_PAYLOAD_SIZE_4096B;
+    default:
+      return PCIE_MAX_PAYLOAD_SIZE_128B;
+  }
+}
 
 /**
   Generic routine to setup the PCI features as per its predetermined defaults.
@@ -91,6 +124,12 @@ SetupDefaultPciExpressDevicePolicy (
   )
 {
 
+  if (mPciExpressPlatformPolicy.Mps) {
+    PciDevice->SetupMPS = EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_AUTO;
+  } else {
+    PciDevice->SetupMPS = EFI_PCI_EXPRESS_NOT_APPLICABLE;
+  }
+
 }
 
 /**
@@ -163,6 +202,15 @@ GetPciExpressDevicePolicy (
     // platform chipset policies are returned for this PCI device
     //
 
+    //
+    // set device specific policy for the Max_Payload_Size
+    //
+    if (mPciExpressPlatformPolicy.Mps) {
+      PciDevice->SetupMPS = PciExpressDevicePolicy.DeviceCtlMPS;
+    } else {
+      PciDevice->SetupMPS = EFI_PCI_EXPRESS_NOT_APPLICABLE;
+    }
+
 
     DEBUG ((
       DEBUG_INFO,
@@ -257,6 +305,28 @@ PciExpressPlatformGetPolicy (
   return Status;
 }
 
+EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE
+GetPciExpressMps (
+  IN UINT8              Mps
+  )
+{
+  switch (Mps) {
+    case PCIE_MAX_PAYLOAD_SIZE_128B:
+      return EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_128B;
+    case PCIE_MAX_PAYLOAD_SIZE_256B:
+      return EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_256B;
+    case PCIE_MAX_PAYLOAD_SIZE_512B:
+      return EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_512B;
+    case PCIE_MAX_PAYLOAD_SIZE_1024B:
+      return EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_1024B;
+    case PCIE_MAX_PAYLOAD_SIZE_2048B:
+      return EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_2048B;
+    case PCIE_MAX_PAYLOAD_SIZE_4096B:
+      return EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_4096B;
+  }
+  return EFI_PCI_EXPRESS_NOT_APPLICABLE;
+}
+
 
 /**
   Notifies the platform about the current PCI Express state of the device.
@@ -277,6 +347,16 @@ PciExpressPlatformNotifyDeviceState (
 {
   EFI_PCI_EXPRESS_DEVICE_CONFIGURATION      PciExDeviceConfiguration;
 
+  //
+  // get the device-specific state for the PCIe Max_Payload_Size feature
+  //
+  if (mPciExpressPlatformPolicy.Mps) {
+    PciExDeviceConfiguration.DeviceCtlMPS = GetPciExpressMps (
+                                              (UINT8)PciDevice->PciExpressCapabilityStructure.DeviceControl.Bits.MaxPayloadSize
+                                              );
+  } else {
+    PciExDeviceConfiguration.DeviceCtlMPS = EFI_PCI_EXPRESS_NOT_APPLICABLE;
+  }
 
   if (mPciExPlatformProtocol != NULL) {
     return mPciExPlatformProtocol->NotifyDeviceState (
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
index 4283b81..5ae6386 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
@@ -84,4 +84,21 @@ EFI_STATUS
 PciExpressPlatformNotifyDeviceState (
   IN PCI_IO_DEVICE                        *PciDevice
   );
+
+/**
+  Routine to translate the given device-specific platform policy from type
+  EFI_PCI_CONF_MAX_PAYLOAD_SIZE to HW-specific value, as per PCI Base Specification
+  Revision 4.0; for the PCI feature Max_Payload_Size.
+
+  @param  MPS     Input device-specific policy should be in terms of type
+                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
+
+  @retval         Range values for the Max_Payload_Size as defined in the PCI
+                  Base Specification 4.0
+**/
+UINT8
+SetDevicePolicyPciExpressMps (
+  IN  UINT8                   MPS
+);
+
 #endif
-- 
2.21.0.windows.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 04/12] PciBusDxe: New PCI Express feature Max_Read_Req_Size
  2020-02-07 20:04 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] PciBusDxe: New PCI Express features Javeed, Ashraf
                   ` (2 preceding siblings ...)
  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 ` 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
                   ` (20 subsequent siblings)
  24 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:04 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2194

The code changes are made to enable the configuration of PCI Express
feature Max_Read_Req_Size (MRRS), which defines the memory read request
size for the PCI transactions, as per the PCI Base Specification 4
Revision 1.

The code changes are made to configure a common value that is applicable
to all the child nodes originating from the root bridge device instance,
based on following 3 criteria:-
(1) if platform defines MRRS device policy for any one PCI device in the
     tree than align all the devices in the PCI tree to that same value
(2) if platform does not provide device policy for any of the devices in
    the PCI tree than setup the MRRS value equivalent to MPS value for
    all PCI devices to meet the criteria for the isochronous traffic
(3) if platform does not provide device policy for any of the devices and
    it has not selected the MPS to be configured either; than the config-
    uration of the MRRS is performed based on highest common value of the
    MPS advertized in the PCI device capability registers of the devices

This programming of MRRS gets the device-specific platform policy using
the new PCI Express Platform Protocol interface, defined in the below
feature request:- https://bugzilla.tianocore.org/show_bug.cgi?id=1954

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 | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h |  45 +++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  |  20 +++++++++++++++++++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h  |   9 +++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c |  81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h |  15 +++++++++++++++
 7 files changed, 360 insertions(+), 1 deletion(-)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index 5dc5f61..77b44c0 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -288,6 +288,7 @@ struct _PCI_IO_DEVICE {
   //
   UINT16                                    BridgeIoAlignment;
   UINT8                                     SetupMPS;
+  UINT8                                     SetupMRRS;
 };
 
 #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 6084446..2810158 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
@@ -191,3 +191,193 @@ ProgramMaxPayloadSize (
   return Status;
 }
 
+EFI_STATUS
+ConditionalCasMaxReadReqSize (
+  IN  PCI_IO_DEVICE                             *PciDevice,
+  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciExpressConfigurationTable
+  )
+{
+  //
+  // align the Max_Read_Request_Size of the PCI tree based on 3 conditions:
+  // first, if user defines MRRS for any one PCI device in the tree than align
+  // all the devices in the PCI tree.
+  // second, if user override is not define for this PCI tree than setup the MRRS
+  // based on MPS value of the tree to meet the criteria for the isochronous
+  // traffic.
+  // third, if no user override, or platform firmware policy has not selected
+  // this PCI bus driver to configure the MPS; than configure the MRRS to a
+  // highest common value of PCI device capability for the MPS found among all
+  // the PCI devices in this tree
+  //
+  if (PciExpressConfigurationTable) {
+    if (PciExpressConfigurationTable->Lock_Max_Read_Request_Size) {
+      PciDevice->SetupMRRS = PciExpressConfigurationTable->Max_Read_Request_Size;
+    } else {
+      if (mPciExpressPlatformPolicy.Mps) {
+        PciDevice->SetupMRRS = PciDevice->SetupMPS;
+      } else {
+        PciDevice->SetupMRRS = MIN (
+                                PciDevice->SetupMRRS,
+                                PciExpressConfigurationTable->Max_Read_Request_Size
+                                );
+      }
+      PciExpressConfigurationTable->Max_Read_Request_Size = PciDevice->SetupMRRS;
+    }
+  }
+  DEBUG (( DEBUG_INFO, "MRRS: %d,", PciDevice->SetupMRRS));
+
+  return EFI_SUCCESS;
+}
+
+/**
+  The main routine which process the PCI feature Max_Read_Req_Size as per the
+  device-specific platform policy, as well as in complaince with the PCI Base
+  specification Revision 4, that aligns the value for the entire PCI heirarchy
+  starting from its physical PCI Root port / Bridge device.
+
+  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
+  @param PciExpressConfigurationTable  pointer to PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
+
+  @retval EFI_SUCCESS                   processing of PCI feature Max_Read_Req_Size
+                                        is successful.
+**/
+EFI_STATUS
+SetupMaxReadReqSize (
+  IN  PCI_IO_DEVICE                           *PciDevice,
+  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciExpressConfigurationTable
+  )
+{
+  PCI_REG_PCIE_DEVICE_CAPABILITY  PciDeviceCap;
+  UINT8                           MrrsValue;
+
+  PciDeviceCap.Uint32 = PciDevice->PciExpressCapabilityStructure.DeviceCapability.Uint32;
+
+  if (PciDevice->SetupMRRS == EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_AUTO) {
+    //
+    // The maximum read request size is not the data packet size of the TLP,
+    // but the memory read request size, and set to the function as a requestor
+    // to not exceed this limit.
+    // However, for the PCI device capable of isochronous traffic; this memory read
+    // request size should not extend beyond the Max_Payload_Size. Thus, in case if
+    // device policy return by platform indicates to set as per device capability
+    // than set as per Max_Payload_Size configuration value
+    //
+    if (mPciExpressPlatformPolicy.Mps) {
+      MrrsValue = PciDevice->SetupMPS;
+    } else {
+      //
+      // in case this driver is not required to configure the Max_Payload_Size
+      // than consider programming HCF of the device capability's Max_Payload_Size
+      // in this PCI hierarchy; thus making this an implementation specific feature
+      // which the platform should avoid. For better results, the platform should
+      // make both the Max_Payload_Size & Max_Read_Request_Size to be configured
+      // by this driver
+      //
+      MrrsValue = (UINT8)PciDeviceCap.Bits.MaxPayloadSize;
+    }
+  } else {
+    //
+    // override as per platform based device policy
+    //
+    MrrsValue = SetDevicePolicyPciExpressMrrs (PciDevice->SetupMRRS);
+    //
+    // align this device's Max_Read_Request_Size value to the entire PCI tree
+    //
+    if (PciExpressConfigurationTable) {
+      if (!PciExpressConfigurationTable->Lock_Max_Read_Request_Size) {
+        PciExpressConfigurationTable->Lock_Max_Read_Request_Size = TRUE;
+        PciExpressConfigurationTable->Max_Read_Request_Size = MrrsValue;
+      } else {
+        //
+        // in case of another user enforced value of MRRS within the same tree,
+        // pick the smallest between the locked value and this value; to set
+        // across entire PCI tree nodes
+        //
+        MrrsValue = MIN (
+                      MrrsValue,
+                      PciExpressConfigurationTable->Max_Read_Request_Size
+                      );
+        PciExpressConfigurationTable->Max_Read_Request_Size = MrrsValue;
+      }
+    }
+  }
+  //
+  // align this device's Max_Read_Request_Size to derived configuration value
+  //
+  PciDevice->SetupMRRS = MrrsValue;
+
+  return ConditionalCasMaxReadReqSize (
+          PciDevice,
+          PciExpressConfigurationTable
+          );
+}
+
+
+/**
+  Overrides the PCI Device Control register Max_Read_Req_Size register field; 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 controller.
+  @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
+ProgramMaxReadReqSize (
+  IN PCI_IO_DEVICE          *PciDevice,
+  IN VOID                   *PciExFeatureConfiguration
+  )
+{
+  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
+  UINT32                      Offset;
+  EFI_STATUS                  Status;
+  EFI_TPL                     OldTpl;
+
+  PcieDev.Uint16 = 0;
+  Offset = PciDevice->PciExpressCapabilityOffset +
+               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint16,
+                                  Offset,
+                                  1,
+                                  &PcieDev.Uint16
+                                  );
+  ASSERT (Status == EFI_SUCCESS);
+
+  if (PcieDev.Bits.MaxReadRequestSize != PciDevice->SetupMRRS) {
+    PcieDev.Bits.MaxReadRequestSize = PciDevice->SetupMRRS;
+    DEBUG (( DEBUG_INFO, "MRRS: %d,", PciDevice->SetupMRRS));
+
+    //
+    // 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,
+                                    &PcieDev.Uint16
+                                    );
+    //
+    // Restore TPL to its original level
+    //
+    gBS->RestoreTPL (OldTpl);
+
+    if (!EFI_ERROR(Status)) {
+      PciDevice->PciExpressCapabilityStructure.DeviceControl.Uint16 = PcieDev.Uint16;
+    } else {
+      ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, Offset);
+    }
+  } else {
+    DEBUG (( DEBUG_INFO, "No MRRS=%d,", PciDevice->SetupMRRS));
+  }
+
+  return Status;
+}
+
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
index 460437b..b43fba7 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
@@ -52,4 +52,49 @@ ProgramMaxPayloadSize (
   IN VOID                   *PciExFeatureConfiguration
   );
 
+
+EFI_STATUS
+ConditionalCasMaxReadReqSize (
+  IN  PCI_IO_DEVICE                             *PciDevice,
+  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciFeaturesConfigurationTable
+  );
+
+/**
+  The main routine which process the PCI feature Max_Read_Req_Size as per the
+  device-specific platform policy, as well as in complaince with the PCI Base
+  specification Revision 4, that aligns the value for the entire PCI heirarchy
+  starting from its physical PCI Root port / Bridge device.
+
+  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
+  @param PciConfigPhase                 for the PCI feature configuration phases:
+                                        PciExpressFeatureSetupPhase & PciExpressFeatureEntendedSetupPhase
+  @param PciFeaturesConfigurationTable  pointer to PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
+
+  @retval EFI_SUCCESS                   processing of PCI feature Max_Read_Req_Size
+                                        is successful.
+**/
+EFI_STATUS
+SetupMaxReadReqSize (
+  IN  PCI_IO_DEVICE                           *PciDevice,
+  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciFeaturesConfigurationTable
+  );
+
+/**
+  Overrides the PCI Device Control register Max_Read_Req_Size register field; 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 controller.
+  @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
+ProgramMaxReadReqSize (
+  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 aae6139..1caf1f4 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -34,7 +34,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY             mPciExpressPlatformPolicy = {
     //
     // support for PCI Express feature - Max. Read Request Size
     //
-    FALSE,
+    TRUE,
     //
     // support for PCI Express feature - Extended Tag
     //
@@ -104,6 +104,15 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT  mPciExpressFeatureInitializationList[]
   },
   {
     PciExpressFeatureProgramPhase,        PciExpressMps,        ProgramMaxPayloadSize
+  },
+  {
+    PciExpressFeatureSetupPhase,          PciExpressMrrs,       SetupMaxReadReqSize
+  },
+  {
+    PciExpressFeatureEntendedSetupPhase,  PciExpressMrrs,       ConditionalCasMaxReadReqSize
+  },
+  {
+    PciExpressFeatureProgramPhase,        PciExpressMrrs,       ProgramMaxReadReqSize
   }
 };
 
@@ -607,6 +616,15 @@ CreatePciRootBridgeDeviceNode (
     // start by assuming 4096B as the default value for the Max. Payload Size
     //
     PciConfigTable->Max_Payload_Size            = PCIE_MAX_PAYLOAD_SIZE_4096B;
+    //
+    // start by assuming 4096B as the default value for the Max. Read Request Size
+    //
+    PciConfigTable->Max_Read_Request_Size       = PCIE_MAX_READ_REQ_SIZE_4096B;
+    //
+    // start by assuming the Max. Read Request Size need not be common for all
+    // the devices in the PCI tree
+    //
+    PciConfigTable->Lock_Max_Read_Request_Size  = FALSE;
   }
 
   RootBridgeNode->PciExFeaturesConfigurationTable  = PciConfigTable;
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
index 4ecbefc..a1fc39c 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
@@ -71,6 +71,15 @@ struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE {
   // size among all the PCI devices in the PCI hierarchy
   //
   UINT8                                     Max_Payload_Size;
+  //
+  // to configure the PCI feature maximum read request size to maintain the memory
+  // requester size among all the PCI devices in the PCI hierarchy
+  //
+  UINT8                                     Max_Read_Request_Size;
+  //
+  // lock the Max_Read_Request_Size for the entire PCI tree of a root port
+  //
+  BOOLEAN                                   Lock_Max_Read_Request_Size;
 };
 
 //
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
index 3e9d4c5..f74e566 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
@@ -115,6 +115,40 @@ SetDevicePolicyPciExpressMps (
   }
 }
 
+/**
+  Routine to translate the given device-specific platform policy from type
+  EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE to HW-specific value, as per PCI Base Specification
+  Revision 4.0; for the PCI feature Max_Read_Req_Size.
+
+  @param  MRRS    Input device-specific policy should be in terms of type
+                  EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE
+
+  @retval         Range values for the Max_Read_Req_Size as defined in the PCI
+                  Base Specification 4.0
+**/
+UINT8
+SetDevicePolicyPciExpressMrrs (
+  IN  UINT8                   MRRS
+)
+{
+  switch (MRRS) {
+    case EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_128B:
+      return PCIE_MAX_READ_REQ_SIZE_128B;
+    case EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_256B:
+      return PCIE_MAX_READ_REQ_SIZE_256B;
+    case EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_512B:
+      return PCIE_MAX_READ_REQ_SIZE_512B;
+    case EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_1024B:
+      return PCIE_MAX_READ_REQ_SIZE_1024B;
+    case EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_2048B:
+      return PCIE_MAX_READ_REQ_SIZE_2048B;
+    case EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_4096B:
+      return PCIE_MAX_READ_REQ_SIZE_4096B;
+    default:
+      return PCIE_MAX_READ_REQ_SIZE_128B;
+  }
+}
+
 /**
   Generic routine to setup the PCI features as per its predetermined defaults.
 **/
@@ -130,6 +164,12 @@ SetupDefaultPciExpressDevicePolicy (
     PciDevice->SetupMPS = EFI_PCI_EXPRESS_NOT_APPLICABLE;
   }
 
+  if (mPciExpressPlatformPolicy.Mrrs) {
+    PciDevice->SetupMRRS = EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_AUTO;
+  } else {
+    PciDevice->SetupMRRS = EFI_PCI_EXPRESS_NOT_APPLICABLE;
+  }
+
 }
 
 /**
@@ -211,6 +251,14 @@ GetPciExpressDevicePolicy (
       PciDevice->SetupMPS = EFI_PCI_EXPRESS_NOT_APPLICABLE;
     }
 
+    //
+    // set device specific policy for Max_Read_Req_Size
+    //
+    if (mPciExpressPlatformPolicy.Mrrs) {
+      PciDevice->SetupMRRS = PciExpressDevicePolicy.DeviceCtlMRRS;
+    } else {
+      PciDevice->SetupMRRS = EFI_PCI_EXPRESS_NOT_APPLICABLE;
+    }
 
     DEBUG ((
       DEBUG_INFO,
@@ -327,6 +375,28 @@ GetPciExpressMps (
   return EFI_PCI_EXPRESS_NOT_APPLICABLE;
 }
 
+EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE
+GetPciExpressMrrs (
+  IN UINT8              Mrrs
+  )
+{
+  switch (Mrrs) {
+    case PCIE_MAX_READ_REQ_SIZE_128B:
+      return EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_128B;
+    case PCIE_MAX_READ_REQ_SIZE_256B:
+      return EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_256B;
+    case PCIE_MAX_READ_REQ_SIZE_512B:
+      return EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_512B;
+    case PCIE_MAX_READ_REQ_SIZE_1024B:
+      return EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_1024B;
+    case PCIE_MAX_READ_REQ_SIZE_2048B:
+      return EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_2048B;
+    case PCIE_MAX_READ_REQ_SIZE_4096B:
+      return EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_4096B;
+  }
+  return EFI_PCI_EXPRESS_NOT_APPLICABLE;
+}
+
 
 /**
   Notifies the platform about the current PCI Express state of the device.
@@ -358,6 +428,17 @@ PciExpressPlatformNotifyDeviceState (
     PciExDeviceConfiguration.DeviceCtlMPS = EFI_PCI_EXPRESS_NOT_APPLICABLE;
   }
 
+  //
+  // get the device-specific state for the PCIe Max_Read_Req_Size feature
+  //
+  if (mPciExpressPlatformPolicy.Mrrs) {
+    PciExDeviceConfiguration.DeviceCtlMRRS = GetPciExpressMrrs (
+                                              (UINT8)PciDevice->PciExpressCapabilityStructure.DeviceControl.Bits.MaxReadRequestSize
+                                              );
+  } else {
+    PciExDeviceConfiguration.DeviceCtlMRRS = EFI_PCI_EXPRESS_NOT_APPLICABLE;
+  }
+
   if (mPciExPlatformProtocol != NULL) {
     return mPciExPlatformProtocol->NotifyDeviceState (
                                     mPciExPlatformProtocol,
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
index 5ae6386..4653c79 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
@@ -101,4 +101,19 @@ SetDevicePolicyPciExpressMps (
   IN  UINT8                   MPS
 );
 
+/**
+  Routine to translate the given device-specific platform policy from type
+  EFI_PCI_CONF_MAX_READ_REQ_SIZE to HW-specific value, as per PCI Base Specification
+  Revision 4.0; for the PCI feature Max_Read_Req_Size.
+
+  @param  MRRS    Input device-specific policy should be in terms of type
+                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
+
+  @retval         Range values for the Max_Read_Req_Size as defined in the PCI
+                  Base Specification 4.0
+**/
+UINT8
+SetDevicePolicyPciExpressMrrs (
+  IN  UINT8                   MRRS
+);
 #endif
-- 
2.21.0.windows.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: New PCI Express feature Relax Ordering
  2020-02-07 20:04 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] PciBusDxe: New PCI Express features Javeed, Ashraf
                   ` (3 preceding siblings ...)
  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 ` 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
                   ` (19 subsequent siblings)
  24 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:04 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2313

The code changes are made to enable the configuration of PCI Express
feature Relax Ordering (OR), that enables the PCI function to initiate
requests if it does not require strong write ordering for its transact-
ions; as per the PCI Express Base Specification 4 Revision 1.

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.

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             |  4 ++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h | 18 ++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  |  5 ++++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 157 insertions(+), 1 deletion(-)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index 77b44c0..d3d795d 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -287,8 +287,12 @@ struct _PCI_IO_DEVICE {
   // This field is used to support this case.
   //
   UINT16                                    BridgeIoAlignment;
+  //
+  // PCI Express features setup flags
+  //
   UINT8                                     SetupMPS;
   UINT8                                     SetupMRRS;
+  PCI_FEATURE_POLICY                        SetupRO;
 };
 
 #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 2810158..3262b76 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
@@ -381,3 +381,73 @@ ProgramMaxReadReqSize (
   return Status;
 }
 
+/**
+  Overrides the PCI Device Control register Relax Order register field; 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
+ProgramRelaxOrder (
+  IN PCI_IO_DEVICE          *PciDevice,
+  IN VOID                   *PciExFeatureConfiguration
+  )
+{
+  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
+  UINT32                      Offset;
+  EFI_STATUS                  Status;
+  EFI_TPL                     OldTpl;
+
+  PcieDev.Uint16 = 0;
+  Offset = PciDevice->PciExpressCapabilityOffset +
+               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint16,
+                                  Offset,
+                                  1,
+                                  &PcieDev.Uint16
+                                  );
+  ASSERT (Status == EFI_SUCCESS);
+
+  if (PciDevice->SetupRO.Override
+      &&  PcieDev.Bits.RelaxedOrdering != PciDevice->SetupRO.Act
+      ) {
+    PcieDev.Bits.RelaxedOrdering = PciDevice->SetupRO.Act;
+    DEBUG (( DEBUG_INFO, "RO=%d,", PciDevice->SetupRO.Act));
+
+    //
+    // 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,
+                                    &PcieDev.Uint16
+                                    );
+    //
+    // Restore TPL to its original level
+    //
+    gBS->RestoreTPL (OldTpl);
+
+    if (!EFI_ERROR(Status)) {
+      PciDevice->PciExpressCapabilityStructure.DeviceControl.Uint16 = PcieDev.Uint16;
+    } else {
+      ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, Offset);
+    }
+  } else {
+    DEBUG (( DEBUG_INFO, "No RO,", PciDevice->SetupRO.Act));
+  }
+
+  return Status;
+}
+
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
index b43fba7..0d17801 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
@@ -97,4 +97,22 @@ ProgramMaxReadReqSize (
   IN VOID                   *PciExFeatureConfiguration
   );
 
+/**
+  Overrides the PCI Device Control register Relax Order register field; 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
+ProgramRelaxOrder (
+  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 1caf1f4..267f570 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -42,7 +42,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY             mPciExpressPlatformPolicy = {
     //
     // support for PCI Express feature - Relax Order
     //
-    FALSE,
+    TRUE,
     //
     // support for PCI Express feature - No-Snoop
     //
@@ -113,6 +113,9 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT  mPciExpressFeatureInitializationList[]
   },
   {
     PciExpressFeatureProgramPhase,        PciExpressMrrs,       ProgramMaxReadReqSize
+  },
+  {
+    PciExpressFeatureProgramPhase,        PciExpressRelaxOrder, ProgramRelaxOrder
   }
 };
 
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
index f74e566..40eb8a3 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
@@ -149,6 +149,45 @@ SetDevicePolicyPciExpressMrrs (
   }
 }
 
+/**
+  Routine to set the device-specific policy for the PCI feature Relax Ordering
+
+  @param  RelaxOrder    value corresponding to data type EFI_PCI_EXPRESS_RELAX_ORDER
+  @param  PciDevice     A pointer to PCI_IO_DEVICE
+**/
+VOID
+SetDevicePolicyPciExpressRo (
+  IN  EFI_PCI_EXPRESS_RELAX_ORDER RelaxOrder,
+  OUT PCI_IO_DEVICE               *PciDevice
+  )
+{
+  //
+  // implementation specific rules for the usage of PCI_FEATURE_POLICY members
+  // exclusively for the PCI Feature Relax Ordering (RO)
+  //
+  // .Override = 0 to skip this PCI feature RO for the PCI device
+  // .Override = 1 to program this RO PCI feature
+  //      .Act = 1 to enable the RO in the PCI device
+  //      .Act = 0 to disable the RO in the PCI device
+  //
+  switch (RelaxOrder) {
+    case  EFI_PCI_EXPRESS_RO_AUTO:
+      PciDevice->SetupRO.Override = 0;
+      break;
+    case  EFI_PCI_EXPRESS_RO_DISABLE:
+      PciDevice->SetupRO.Override = 1;
+      PciDevice->SetupRO.Act = 0;
+      break;
+    case  EFI_PCI_EXPRESS_RO_ENABLE:
+      PciDevice->SetupRO.Override = 1;
+      PciDevice->SetupRO.Act = 1;
+      break;
+    default:
+      PciDevice->SetupRO.Override = 0;
+      break;
+  }
+}
+
 /**
   Generic routine to setup the PCI features as per its predetermined defaults.
 **/
@@ -170,6 +209,8 @@ SetupDefaultPciExpressDevicePolicy (
     PciDevice->SetupMRRS = EFI_PCI_EXPRESS_NOT_APPLICABLE;
   }
 
+  PciDevice->SetupRO.Override = 0;
+
 }
 
 /**
@@ -259,6 +300,15 @@ GetPciExpressDevicePolicy (
     } else {
       PciDevice->SetupMRRS = EFI_PCI_EXPRESS_NOT_APPLICABLE;
     }
+    //
+    // set device specific policy for Relax Ordering
+    //
+    if (mPciExpressPlatformPolicy.RelaxOrder) {
+      SetDevicePolicyPciExpressRo (PciExpressDevicePolicy.DeviceCtlRelaxOrder, PciDevice);
+    } else {
+      PciDevice->SetupRO.Override = 0;
+    }
+
 
     DEBUG ((
       DEBUG_INFO,
@@ -438,6 +488,17 @@ PciExpressPlatformNotifyDeviceState (
   } else {
     PciExDeviceConfiguration.DeviceCtlMRRS = EFI_PCI_EXPRESS_NOT_APPLICABLE;
   }
+  //
+  // get the device-specific state for the PCIe Relax Order feature
+  //
+  if (mPciExpressPlatformPolicy.RelaxOrder) {
+    PciExDeviceConfiguration.DeviceCtlRelaxOrder = PciDevice->PciExpressCapabilityStructure.DeviceControl.Bits.RelaxedOrdering
+                                                      ? EFI_PCI_EXPRESS_RO_ENABLE
+                                                      : EFI_PCI_EXPRESS_RO_DISABLE;
+  } else {
+    PciExDeviceConfiguration.DeviceCtlRelaxOrder = EFI_PCI_EXPRESS_NOT_APPLICABLE;
+  }
+
 
   if (mPciExPlatformProtocol != NULL) {
     return mPciExPlatformProtocol->NotifyDeviceState (
-- 
2.21.0.windows.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 06/12] PciBusDxe: New PCI Express feature No-Snoop
  2020-02-07 20:04 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] PciBusDxe: New PCI Express features Javeed, Ashraf
                   ` (4 preceding siblings ...)
  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 ` Javeed, Ashraf
  2020-02-07 20:04 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] PciBusDxe: New PCI Express feature Completion Timeout Javeed, Ashraf
                   ` (18 subsequent siblings)
  24 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:04 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

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 No-Snoop
(NS), that enables the PCI function to initiate requests if it does not
require hardware enforced cache-coherency for its transactions.

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.

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 | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h | 18 ++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  |  5 ++++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 155 insertions(+), 1 deletion(-)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index d3d795d..e610b52 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -293,6 +293,7 @@ struct _PCI_IO_DEVICE {
   UINT8                                     SetupMPS;
   UINT8                                     SetupMRRS;
   PCI_FEATURE_POLICY                        SetupRO;
+  PCI_FEATURE_POLICY                        SetupNS;
 };
 
 #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 3262b76..df85366 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
@@ -451,3 +451,73 @@ ProgramRelaxOrder (
   return Status;
 }
 
+/**
+  Overrides the PCI Device Control register No-Snoop register field; 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
+ProgramNoSnoop (
+  IN PCI_IO_DEVICE          *PciDevice,
+  IN VOID                   *PciExFeatureConfiguration
+  )
+{
+  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
+  UINT32                      Offset;
+  EFI_STATUS                  Status;
+  EFI_TPL                     OldTpl;
+
+  PcieDev.Uint16 = 0;
+  Offset = PciDevice->PciExpressCapabilityOffset +
+               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint16,
+                                  Offset,
+                                  1,
+                                  &PcieDev.Uint16
+                                  );
+  ASSERT (Status == EFI_SUCCESS);
+
+  if (PciDevice->SetupNS.Override
+      &&  PcieDev.Bits.NoSnoop != PciDevice->SetupNS.Act
+      ) {
+    PcieDev.Bits.NoSnoop = PciDevice->SetupNS.Act;
+    DEBUG (( DEBUG_INFO, "NS=%d", PciDevice->SetupNS.Act));
+
+    //
+    // 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,
+                                    &PcieDev.Uint16
+                                    );
+    //
+    // Restore TPL to its original level
+    //
+    gBS->RestoreTPL (OldTpl);
+
+    if (!EFI_ERROR(Status)) {
+      PciDevice->PciExpressCapabilityStructure.DeviceControl.Uint16 = PcieDev.Uint16;
+    } else {
+      ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, Offset);
+    }
+  } else {
+    DEBUG (( DEBUG_INFO, "No NS,", PciDevice->SetupRO.Act));
+  }
+
+  return Status;
+}
+
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
index 0d17801..ee636ce 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
@@ -115,4 +115,22 @@ ProgramRelaxOrder (
   IN VOID                   *PciExFeatureConfiguration
   );
 
+/**
+  Overrides the PCI Device Control register No-Snoop register field; 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
+ProgramNoSnoop (
+  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 267f570..d264d13 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -46,7 +46,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY             mPciExpressPlatformPolicy = {
     //
     // support for PCI Express feature - No-Snoop
     //
-    FALSE,
+    TRUE,
     //
     // support for PCI Express feature - ASPM state
     //
@@ -116,6 +116,9 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT  mPciExpressFeatureInitializationList[]
   },
   {
     PciExpressFeatureProgramPhase,        PciExpressRelaxOrder, ProgramRelaxOrder
+  },
+  {
+    PciExpressFeatureProgramPhase,        PciExpressNoSnoop,    ProgramNoSnoop
   }
 };
 
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
index 40eb8a3..954ce16 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
@@ -188,6 +188,46 @@ SetDevicePolicyPciExpressRo (
   }
 }
 
+/**
+  Routine to set the device-specific policy for the PCI feature No-Snoop enable
+  or disable
+
+  @param  NoSnoop       value corresponding to data type EFI_PCI_EXPRESS_NO_SNOOP
+  @param  PciDevice     A pointer to PCI_IO_DEVICE
+**/
+VOID
+SetDevicePolicyPciExpressNs (
+  IN  EFI_PCI_EXPRESS_NO_SNOOP  NoSnoop,
+  OUT PCI_IO_DEVICE             *PciDevice
+  )
+{
+  //
+  // implementation specific rules for the usage of PCI_FEATURE_POLICY members
+  // exclusively for the PCI Feature No-Snoop
+  //
+  // .Override = 0 to skip this PCI feature No-Snoop for the PCI device
+  // .Override = 1 to program this No-Snoop PCI feature
+  //      .Act = 1 to enable the No-Snoop in the PCI device
+  //      .Act = 0 to disable the No-Snoop in the PCI device
+  //
+  switch (NoSnoop) {
+    case  EFI_PCI_EXPRESS_NS_AUTO:
+      PciDevice->SetupNS.Override = 0;
+      break;
+    case  EFI_PCI_EXPRESS_NS_DISABLE:
+      PciDevice->SetupNS.Override = 1;
+      PciDevice->SetupNS.Act = 0;
+      break;
+    case  EFI_PCI_EXPRESS_NS_ENABLE:
+      PciDevice->SetupNS.Override = 1;
+      PciDevice->SetupNS.Act = 1;
+      break;
+    default:
+      PciDevice->SetupNS.Override = 0;
+      break;
+  }
+}
+
 /**
   Generic routine to setup the PCI features as per its predetermined defaults.
 **/
@@ -211,6 +251,8 @@ SetupDefaultPciExpressDevicePolicy (
 
   PciDevice->SetupRO.Override = 0;
 
+  PciDevice->SetupNS.Override = 0;
+
 }
 
 /**
@@ -309,6 +351,15 @@ GetPciExpressDevicePolicy (
       PciDevice->SetupRO.Override = 0;
     }
 
+    //
+    // set the device specific policy for No-Snoop
+    //
+    if (mPciExpressPlatformPolicy.NoSnoop) {
+      SetDevicePolicyPciExpressNs (PciExpressDevicePolicy.DeviceCtlNoSnoop, PciDevice);
+    } else {
+      PciDevice->SetupNS.Override = 0;
+    }
+
 
     DEBUG ((
       DEBUG_INFO,
@@ -499,6 +550,17 @@ PciExpressPlatformNotifyDeviceState (
     PciExDeviceConfiguration.DeviceCtlRelaxOrder = EFI_PCI_EXPRESS_NOT_APPLICABLE;
   }
 
+  //
+  // get the device-specific state for the PCIe NoSnoop feature
+  //
+  if (mPciExpressPlatformPolicy.NoSnoop) {
+    PciExDeviceConfiguration.DeviceCtlNoSnoop = PciDevice->PciExpressCapabilityStructure.DeviceControl.Bits.NoSnoop
+                                                    ? EFI_PCI_EXPRESS_NS_ENABLE
+                                                    : EFI_PCI_EXPRESS_NS_DISABLE;
+  } else {
+    PciExDeviceConfiguration.DeviceCtlNoSnoop = EFI_PCI_EXPRESS_NOT_APPLICABLE;
+  }
+
 
   if (mPciExPlatformProtocol != NULL) {
     return mPciExPlatformProtocol->NotifyDeviceState (
-- 
2.21.0.windows.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] PciBusDxe: New PCI Express feature Completion Timeout
  2020-02-07 20:04 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] PciBusDxe: New PCI Express features Javeed, Ashraf
                   ` (5 preceding siblings ...)
  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
  2020-02-07 20:04 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12] PciBusDxe: New PCI Express feature AtomicOp Javeed, Ashraf
                   ` (17 subsequent siblings)
  24 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:04 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

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


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12] PciBusDxe: New PCI Express feature AtomicOp
  2020-02-07 20:04 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] PciBusDxe: New PCI Express features Javeed, Ashraf
                   ` (6 preceding siblings ...)
  2020-02-07 20:04 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] PciBusDxe: New PCI Express feature Completion Timeout Javeed, Ashraf
@ 2020-02-07 20:04 ` Javeed, Ashraf
  2020-02-07 20:04 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 09/12] PciBusDxe: New PCI Express feature LTR Javeed, Ashraf
                   ` (16 subsequent siblings)
  24 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:04 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2499

This code change handles two PCI Express features related to AtomicOp,
in compliance with the PCI Express Base SPecification 5:
(1) configuring PCI function as an AtomicOp Requester
(2) Enabling of Port Egress blocking depending on AtomicOp Routing
    Capability

These is programmed based on the following criteria:-
For a PCI Bridge device:
 - enables as AtomicOp Requester solely based on platform provided device
   policy
 - enabling of Port Egress blocking is based on platform device policy;
   only if its device capability register's AtomicOp Routing bit is 1

For an PCI EndPoint (EP) device:
 - if the platform's device policy wants to enable the AtomicOp Requester
   function for this device, than this device is enabled if all its bridge
   devices have the AtomicOp Routing capability bit set
 - Enabling of Port Egress disable is not applicable to PCI EP device

For an PCI RCiEP device:
 - the AtomicOp Requester functionality is enabled solely based on the
   device policy provided by platform
 - similar to PCI EP device, the enabling of port Egress blocking is not
   applicable

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 | 161 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h |  35 +++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  |  23 ++++++++++++++++++++++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h  |   5 +++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c |  23 +++++++++++++++++++++++
 6 files changed, 247 insertions(+), 1 deletion(-)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index 9b03c12..57ef1b2 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -295,6 +295,7 @@ struct _PCI_IO_DEVICE {
   PCI_FEATURE_POLICY                        SetupRO;
   PCI_FEATURE_POLICY                        SetupNS;
   PCI_FEATURE_POLICY                        SetupCTO;
+  EFI_PCI_EXPRESS_ATOMIC_OP                 SetupAtomicOp;
 };
 
 #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 f3f4d39..5c76ba4 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
@@ -908,3 +908,164 @@ ProgramCompletionTimeout (
   return Status;
 }
 
+/**
+  Routine to setup the AtomicOp Requester in the PCI device, verifies the routing
+  support in the bridge devices, to be complaint as per the PCI Base specification.
+
+  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
+  @param PciExFeatureConfiguration      pointer to common configuration table to
+                                        initialize the PCI Express feature
+
+  @retval EFI_SUCCESS                   bridge device routing capability is successful.
+          EFI_INVALID_PARAMETER         input parameter is NULL
+**/
+EFI_STATUS
+SetupAtomicOpRoutingSupport (
+  IN PCI_IO_DEVICE                              *PciDevice,
+  IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE   *PciExFeatureConfiguration
+  )
+{
+  //
+  // to enable the AtomicOp Requester in the PCI EP device; its Root Port (bridge),
+  // and its PCIe switch upstream & downstream ports (if present) needs to support
+  // the AtomicOp Routing capability.
+  //
+  if (IS_PCI_BRIDGE (&PciDevice->Pci)) {
+    if (!PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Bits.AtomicOpRouting) {
+      //
+      // since the AtomicOp Routing support flag is initialized as TRUE, negate
+      // in case if any of the PCI Bridge device in the PCI tree does not support
+      // the AtomicOp Routing capability
+      //
+      if (PciExFeatureConfiguration == NULL) {
+        return EFI_INVALID_PARAMETER;
+      }
+      PciExFeatureConfiguration->AtomicOpRoutingSupported = FALSE;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Overrides the PCI Device Control 2 register AtomicOp Requester enable field; 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
+ProgramAtomicOp (
+  IN PCI_IO_DEVICE                            *PciDevice,
+  IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExFeatureConfiguration
+  )
+{
+  PCI_REG_PCIE_DEVICE_CONTROL2  PcieDev;
+  UINT32                        Offset;
+  EFI_STATUS                    Status;
+  EFI_TPL                       OldTpl;
+
+  PcieDev.Uint16 = 0;
+  Offset = PciDevice->PciExpressCapabilityOffset +
+               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2);
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint16,
+                                  Offset,
+                                  1,
+                                  &PcieDev.Uint16
+                                  );
+  ASSERT (Status == EFI_SUCCESS);
+
+  if (PciDevice->SetupAtomicOp.Override) {
+    //
+    // override AtomicOp requester device control bit of the device based on the
+    // platform request
+    //
+    if (IS_PCI_BRIDGE (&PciDevice->Pci)) {
+      //
+      // for a bridge device as AtomicOp Requester function; only platform override
+      // request is used to set the device control register
+      //
+      if (PcieDev.Bits.AtomicOpRequester != PciDevice->SetupAtomicOp.Enable_AtomicOpRequester) {
+        PcieDev.Bits.AtomicOpRequester = PciDevice->SetupAtomicOp.Enable_AtomicOpRequester;
+      }
+      //
+      // if platform also request its AtomicOp Egress blocking to be enabled; set
+      // only if its device capability's AtomicOpRouting bit is 1.
+      // applicable to only the bridge devices
+      //
+      if (PciDevice->SetupAtomicOp.Enable_AtomicOpEgressBlocking) {
+        if (PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Bits.AtomicOpRouting) {
+          PcieDev.Bits.AtomicOpEgressBlocking = 1;
+        }
+      }
+    } else {
+      //
+      // in the case of non-bridge device
+      //
+      if (PciExFeatureConfiguration) {
+        //
+        // for a device as AtomicOp Requester function; its bridge devices should
+        // support the AtomicOp Routing capability to enable the device's as a
+        // requester function
+        //
+        if (PciExFeatureConfiguration->AtomicOpRoutingSupported) {
+          if (PcieDev.Bits.AtomicOpRequester != PciDevice->SetupAtomicOp.Enable_AtomicOpRequester) {
+            PcieDev.Bits.AtomicOpRequester = PciDevice->SetupAtomicOp.Enable_AtomicOpRequester;
+          }
+        }
+      } else {
+        //
+        // for the RCiEP device or the bridge device without any child, setup AtomicOp
+        // Requester as per platform's device policy
+        //
+        if (PcieDev.Bits.AtomicOpRequester != PciDevice->SetupAtomicOp.Enable_AtomicOpRequester) {
+          PcieDev.Bits.AtomicOpRequester = PciDevice->SetupAtomicOp.Enable_AtomicOpRequester;
+        }
+      }
+      //
+      // the enabling of AtomicOp Egress Blocking is not applicable to a non-bridge
+      // device
+      //
+    }
+    DEBUG ((
+      DEBUG_INFO,
+      "AtomicOp=%d,",
+      PcieDev.Bits.AtomicOpRequester
+      ));
+
+    //
+    // 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,
+                                    &PcieDev.Uint16
+                                    );
+    //
+    // Restore TPL to its original level
+    //
+    gBS->RestoreTPL (OldTpl);
+
+    if (!EFI_ERROR(Status)) {
+      PciDevice->PciExpressCapabilityStructure.DeviceControl2.Uint16 = PcieDev.Uint16;
+    } else {
+      ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, Offset);
+    }
+  } else {
+    DEBUG (( DEBUG_INFO, "No AtomicOp,"));
+  }
+
+  return Status;
+}
+
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
index 2ee7d4d..1e287fc 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
@@ -168,4 +168,39 @@ ProgramCompletionTimeout (
   IN VOID                   *PciExFeatureConfiguration
   );
 
+/**
+  Routine to setup the AtomicOp Requester in the PCI device, verifies the routing
+  support in the bridge devices, to be complaint as per the PCI Base specification.
+
+  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
+  @param PciExFeatureConfiguration      pointer to common configuration table to
+                                        initialize the PCI Express feature
+
+  @retval EFI_SUCCESS                   bridge device routing capability is successful.
+          EFI_INVALID_PARAMETER         input parameter is NULL
+**/
+EFI_STATUS
+SetupAtomicOpRoutingSupport (
+  IN PCI_IO_DEVICE                              *PciDevice,
+  IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE   *PciExFeatureConfiguration
+  );
+
+/**
+  Overrides the PCI Device Control 2 register AtomicOp Requester enable field; 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
+ProgramAtomicOp (
+  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 d4459f3..9d624a0 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -62,7 +62,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY             mPciExpressPlatformPolicy = {
     //
     // support for PCI Express feature - Atomic Op
     //
-    FALSE,
+    TRUE,
     //
     // support for PCI Express feature - LTR
     //
@@ -125,6 +125,12 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT  mPciExpressFeatureInitializationList[]
   },
   {
     PciExpressFeatureProgramPhase,        PciExpressCto,        ProgramCompletionTimeout
+  },
+  {
+    PciExpressFeatureSetupPhase,          PciExpressAtomicOp,   SetupAtomicOpRoutingSupport
+  },
+  {
+    PciExpressFeatureProgramPhase,        PciExpressAtomicOp,   ProgramAtomicOp
   }
 };
 
@@ -297,6 +303,16 @@ IsPciExpressFeatureExtendedSetupRequired (
         && PciExpressPolicy[mPciExpressFeatureInitializationList[idx].PciExpressFeatureId] == TRUE
     ) {
       return TRUE;
+    } else if (
+        //
+        // the PCI Express feature does not require extended setup phase but it
+        // does require global flag to track the AtomicOpRouting caoability to
+        // be tracked for all its bridge devices
+        //
+        idx == PciExpressAtomicOp
+        && PciExpressPolicy[idx] == TRUE
+        ) {
+      return TRUE;
     }
   }
 
@@ -637,6 +653,11 @@ CreatePciRootBridgeDeviceNode (
     // the devices in the PCI tree
     //
     PciConfigTable->Lock_Max_Read_Request_Size  = FALSE;
+    //
+    // start by assuming the AtomicOp Routing capability is supported in the PCI
+    // tree
+    //
+    PciConfigTable->AtomicOpRoutingSupported    = TRUE;
   }
 
   RootBridgeNode->PciExFeaturesConfigurationTable  = PciConfigTable;
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
index a1fc39c..2bd565e 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
@@ -80,6 +80,11 @@ struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE {
   // lock the Max_Read_Request_Size for the entire PCI tree of a root port
   //
   BOOLEAN                                   Lock_Max_Read_Request_Size;
+  //
+  // to record the AtomicOp Routing capability of the PCI Heirarchy to enable
+  // the AtomicOp of the EP device
+  //
+  BOOLEAN                                   AtomicOpRoutingSupported;
 };
 
 //
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
index 1afea19..2707976 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
@@ -334,6 +334,8 @@ SetupDefaultPciExpressDevicePolicy (
 
   PciDevice->SetupCTO.Override = 0;
 
+  PciDevice->SetupAtomicOp.Override = 0;
+
 }
 
 /**
@@ -450,6 +452,14 @@ GetPciExpressDevicePolicy (
       PciDevice->SetupCTO.Override = 0;
     }
 
+    //
+    // set the device-specific policy for AtomicOp
+    //
+    if (mPciExpressPlatformPolicy.AtomicOp) {
+      PciDevice->SetupAtomicOp = PciExpressDevicePolicy.DeviceCtl2AtomicOp;
+    } else {
+      PciDevice->SetupAtomicOp.Override = 0;
+    }
 
     DEBUG ((
       DEBUG_INFO,
@@ -692,6 +702,19 @@ PciExpressPlatformNotifyDeviceState (
     PciExDeviceConfiguration.CTOsupport = EFI_PCI_EXPRESS_NOT_APPLICABLE;
   }
 
+  //
+  // get the device-specific state for the PCIe AtomicOp feature
+  //
+  if (mPciExpressPlatformPolicy.AtomicOp) {
+    PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpRequester
+    = (UINT8)PciDevice->PciExpressCapabilityStructure.DeviceControl2.Bits.AtomicOpRequester;
+    PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpEgressBlocking
+    = (UINT8)PciDevice->PciExpressCapabilityStructure.DeviceControl2.Bits.AtomicOpEgressBlocking;
+  } else {
+    PciExDeviceConfiguration.DeviceCtl2AtomicOp.Override = 0;
+    PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpRequester = 0;
+    PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpEgressBlocking = 0;
+  }
 
   if (mPciExPlatformProtocol != NULL) {
     return mPciExPlatformProtocol->NotifyDeviceState (
-- 
2.21.0.windows.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 09/12] PciBusDxe: New PCI Express feature LTR
  2020-02-07 20:04 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] PciBusDxe: New PCI Express features Javeed, Ashraf
                   ` (7 preceding siblings ...)
  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 ` 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
                   ` (15 subsequent siblings)
  24 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:04 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2499

This code change enables the PCI Express feature LTR, in compliance
with the PCI Express Base Specification 5, as well as in accordance its
device policy, as follows:
(1) all the devices capability register needs to indicate that LTR mecha-
    nism is supported. ANy device not capable shall lead to all devices
    state in LTR disable
(2) if device policy of any device requests LTR mechanism enabled, than
    based on above condition (1) is TRUE, all of the devices from root
    bridge are enabled.
(3) Even in case of RCiEP device without any root bridge device; if device
    policy requests LTR enabled and device capability does not support LTR
    shall enforce the default LTR disabled state for that device

This programming of LTR, gets the device-specific platform policy using
the new PCI Express Platform Protocol interface (ECR version 0.8), defined
in the below feature request:-
  https://bugzilla.tianocore.org/show_bug.cgi?id=1954

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 | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h |  40 ++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  |  19 ++++++++++++++++++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h  |   9 +++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c |  53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 292 insertions(+), 1 deletion(-)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index 57ef1b2..7e43a26 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -296,6 +296,7 @@ struct _PCI_IO_DEVICE {
   PCI_FEATURE_POLICY                        SetupNS;
   PCI_FEATURE_POLICY                        SetupCTO;
   EFI_PCI_EXPRESS_ATOMIC_OP                 SetupAtomicOp;
+  BOOLEAN                                   SetupLtr;
 };
 
 #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 5c76ba4..63a243b 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
@@ -1069,3 +1069,174 @@ ProgramAtomicOp (
   return Status;
 }
 
+/**
+  The main routine which process the PCI feature LTR enable/disable as per the
+  device-specific platform policy, as well as in complaince with the PCI Express
+  Base specification Revision 5.
+
+  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
+  @param PciExpressConfigurationTable  pointer to PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
+
+  @retval EFI_SUCCESS                   setup of PCI feature LTR is successful.
+**/
+EFI_STATUS
+SetupLtr (
+  IN  PCI_IO_DEVICE                             *PciDevice,
+  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciExpressConfigurationTable
+  )
+{
+  PCI_REG_PCIE_DEVICE_CAPABILITY2 DeviceCap2;
+  //
+  // as per the PCI-Express Base Specification, in order to enable LTR mechanism
+  // in the upstream ports, all the upstream ports and its downstream ports has
+  // to support the LTR mechanism reported in its Device Capability 2 register
+  //
+  DeviceCap2.Uint32 = PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Uint32;
+
+  if (PciExpressConfigurationTable) {
+    //
+    // in this phase establish 2 requirements:
+    // (1) all the PCI devices in the hierarchy supports the LTR mechanism
+    // (2) check and record any device-specific platform policy that wants to
+    //     enable the LTR mechanism
+    //
+    if (!PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Bits.LtrMechanism) {
+
+      //
+      // it starts with the assumption that all the PCI devices support LTR mechanism
+      // and negates the flag if any PCI device Device Capability 2 register advertizes
+      // as not supported
+      //
+      PciExpressConfigurationTable->LtrSupported = FALSE;
+    }
+
+    if (PciDevice->SetupLtr == TRUE) {
+      //
+      // it starts with the assumption that device-specific platform policy would
+      // be set to LTR disable, and negates the flag if any PCI device platform
+      // policy wants to override to enable the LTR mechanism
+      //
+      PciExpressConfigurationTable->LtrEnable = TRUE;
+    }
+  } else {
+    //
+    // in case of RCiEP device or the bridge device with out any child device,
+    // overrule the device policy if the device in not capable
+    //
+    if (!PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Bits.LtrMechanism
+        && PciDevice->SetupLtr == TRUE) {
+      PciDevice->SetupLtr = FALSE;
+    }
+    //
+    // for any bridge device which is Hot-Plug capable, it is expected that platform
+    // will not enforce the enabling of LTR mechanism only for the bridge device
+    //
+  }
+
+  DEBUG (( DEBUG_INFO, "LTR En: %d (LTR Cap: %d),",
+    PciDevice->SetupLtr ? 1 : 0,
+    PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Bits.LtrMechanism
+    ));
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ReSetupLtr (
+  IN  PCI_IO_DEVICE                             *PciDevice,
+  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciExpressConfigurationTable
+  )
+{
+  //
+  // not applicable to RCiEP device...
+  // for the bridge device without any child device, the policy is already overruled
+  // based on capability in the above routine
+  //
+  if (PciExpressConfigurationTable) {
+    //
+    // in this phase align the device policy to enable LTR policy of any PCI device
+    // in the tree if all the devices are capable to support the LTR mechanism
+    //
+    if (PciExpressConfigurationTable->LtrSupported == TRUE
+        && PciExpressConfigurationTable->LtrEnable == TRUE
+    ) {
+      PciDevice->SetupLtr = TRUE;
+    } else {
+      PciDevice->SetupLtr = FALSE;
+    }
+  }
+
+  DEBUG (( DEBUG_INFO, "LTR En: %d (LTR Cap: %d),",
+    PciDevice->SetupLtr ? 1 : 0,
+    PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Bits.LtrMechanism
+    ));
+  return EFI_SUCCESS;
+}
+
+/**
+  Program the PCI Device Control 2 register LTR mechanism field; 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
+ProgramLtr (
+  IN PCI_IO_DEVICE          *PciDevice,
+  IN VOID                   *PciExFeatureConfiguration
+  )
+{
+  PCI_REG_PCIE_DEVICE_CONTROL2  PcieDev;
+  UINT32                        Offset;
+  EFI_STATUS                    Status;
+  EFI_TPL                       OldTpl;
+
+  PcieDev.Uint16 = 0;
+  Offset = PciDevice->PciExpressCapabilityOffset +
+               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2);
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint16,
+                                  Offset,
+                                  1,
+                                  &PcieDev.Uint16
+                                  );
+  ASSERT (Status == EFI_SUCCESS);
+
+  if (PciDevice->SetupLtr != (BOOLEAN) PcieDev.Bits.LtrMechanism) {
+    PcieDev.Bits.LtrMechanism = PciDevice->SetupLtr ? 1 : 0;
+    DEBUG (( DEBUG_INFO, "LTR=%d,", PcieDev.Bits.LtrMechanism));
+
+    //
+    // 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,
+                                    &PcieDev.Uint16
+                                    );
+    //
+    // Restore TPL to its original level
+    //
+    gBS->RestoreTPL (OldTpl);
+
+    if (!EFI_ERROR(Status)) {
+      PciDevice->PciExpressCapabilityStructure.DeviceControl2.Uint16 = PcieDev.Uint16;
+    } else {
+      ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, Offset);
+    }
+  } else {
+    DEBUG (( DEBUG_INFO, "no LTR,"));
+  }
+
+  return Status;
+}
+
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
index 1e287fc..374fe49 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
@@ -203,4 +203,44 @@ ProgramAtomicOp (
   IN VOID                   *PciExFeatureConfiguration
   );
 
+/**
+  The main routine which process the PCI feature LTR enable/disable as per the
+  device-specific platform policy, as well as in complaince with the PCI Express
+  Base specification Revision 5.
+
+  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
+  @param PciFeaturesConfigurationTable  pointer to PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
+
+  @retval EFI_SUCCESS                   setup of PCI feature LTR is successful.
+**/
+EFI_STATUS
+SetupLtr (
+  IN  PCI_IO_DEVICE                             *PciDevice,
+  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciFeaturesConfigurationTable
+  );
+
+EFI_STATUS
+ReSetupLtr (
+  IN  PCI_IO_DEVICE                             *PciDevice,
+  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciFeaturesConfigurationTable
+  );
+
+/**
+  Program the PCI Device Control 2 register LTR mechanism field; 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
+ProgramLtr (
+  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 9d624a0..bdeb0d2 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -66,7 +66,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY             mPciExpressPlatformPolicy = {
     //
     // support for PCI Express feature - LTR
     //
-    FALSE,
+    TRUE,
     //
     // support for PCI Express feature - PTM
     //
@@ -131,6 +131,15 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT  mPciExpressFeatureInitializationList[]
   },
   {
     PciExpressFeatureProgramPhase,        PciExpressAtomicOp,   ProgramAtomicOp
+  },
+  {
+    PciExpressFeatureSetupPhase,          PciExpressLtr,        SetupLtr
+  },
+  {
+    PciExpressFeatureEntendedSetupPhase,  PciExpressLtr,        ReSetupLtr
+  },
+  {
+    PciExpressFeatureProgramPhase,        PciExpressLtr,        ProgramLtr
   }
 };
 
@@ -654,6 +663,14 @@ CreatePciRootBridgeDeviceNode (
     //
     PciConfigTable->Lock_Max_Read_Request_Size  = FALSE;
     //
+    // start by assuming the LTR mechanism is supported in a PCI tree
+    //
+    PciConfigTable->LtrSupported                = TRUE;
+    //
+    // the default LTR mechanism is disabled as per the PCI Base specification
+    //
+    PciConfigTable->LtrEnable                   = FALSE;
+    //
     // start by assuming the AtomicOp Routing capability is supported in the PCI
     // tree
     //
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
index 2bd565e..5dded7c 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
@@ -81,6 +81,15 @@ struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE {
   //
   BOOLEAN                                   Lock_Max_Read_Request_Size;
   //
+  // to record the adversity in LTR mechanism support capability among the PCI
+  // device of an heirarchy
+  //
+  BOOLEAN                                   LtrSupported;
+  //
+  // to enable the LTR mechansim for the entire PCI tree from a root port
+  //
+  BOOLEAN                                   LtrEnable;
+  //
   // to record the AtomicOp Routing capability of the PCI Heirarchy to enable
   // the AtomicOp of the EP device
   //
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
index 2707976..83b3aa7 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
@@ -307,6 +307,36 @@ SetDevicePolicyPciExpressCto (
   }
 }
 
+/**
+  Routine to set the device-specific policy for the PCI feature LTR enable/disable
+
+  @param  AtomicOp      value corresponding to data type EFI_PCI_EXPRESS_ATOMIC_OP
+  @param  PciDevice     A pointer to PCI_IO_DEVICE
+
+**/
+VOID
+SetDevicePolicyPciExpressLtr (
+  IN  EFI_PCI_EXPRESS_LTR            Ltr,
+  OUT PCI_IO_DEVICE               *PciDevice
+  )
+{
+  switch (Ltr){
+    case EFI_PCI_EXPRESS_LTR_AUTO:
+    case EFI_PCI_EXPRESS_LTR_DISABLE:
+      //
+      // leave the LTR mechanism disable or restore to its default state
+      //
+      PciDevice->SetupLtr = FALSE;
+      break;
+    case EFI_PCI_EXPRESS_LTR_ENABLE:
+      //
+      // LTR mechanism enable
+      //
+      PciDevice->SetupLtr = TRUE;
+      break;
+  }
+}
+
 /**
   Generic routine to setup the PCI features as per its predetermined defaults.
 **/
@@ -336,6 +366,8 @@ SetupDefaultPciExpressDevicePolicy (
 
   PciDevice->SetupAtomicOp.Override = 0;
 
+  PciDevice->SetupLtr = FALSE;
+
 }
 
 /**
@@ -461,6 +493,16 @@ GetPciExpressDevicePolicy (
       PciDevice->SetupAtomicOp.Override = 0;
     }
 
+    //
+    // set the device-specific policy for LTR mechanism in the function
+    //
+    if (mPciExpressPlatformPolicy.Ltr) {
+      SetDevicePolicyPciExpressLtr (PciExpressDevicePolicy.DeviceCtl2LTR, PciDevice);
+    } else {
+      PciDevice->SetupLtr = FALSE;
+    }
+
+
     DEBUG ((
       DEBUG_INFO,
       "[device policy: platform]"
@@ -715,6 +757,17 @@ PciExpressPlatformNotifyDeviceState (
     PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpRequester = 0;
     PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpEgressBlocking = 0;
   }
+  //
+  // get the device-specific state for LTR mechanism in the function
+  //
+  if (mPciExpressPlatformPolicy.Ltr) {
+    PciExDeviceConfiguration.DeviceCtl2LTR = PciDevice->PciExpressCapabilityStructure.DeviceControl2.Bits.LtrMechanism
+                                                ? EFI_PCI_EXPRESS_LTR_ENABLE
+                                                : EFI_PCI_EXPRESS_LTR_DISABLE;
+  } else {
+    PciExDeviceConfiguration.DeviceCtl2LTR = EFI_PCI_EXPRESS_NOT_APPLICABLE;
+  }
+
 
   if (mPciExPlatformProtocol != NULL) {
     return mPciExPlatformProtocol->NotifyDeviceState (
-- 
2.21.0.windows.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 10/12] PciBusDxe: New PCI Express feature Extended Tag
  2020-02-07 20:04 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] PciBusDxe: New PCI Express features Javeed, Ashraf
                   ` (8 preceding siblings ...)
  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 ` 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
                   ` (14 subsequent siblings)
  24 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:04 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2499

This code change enables the PCI Express feature Extended Tag, in
compliance with the PCI Express Base Specification 5, and uses the device
policy under the following conditions:
(1) As per the PCI Express Base Specification, all the devices under the
    root bridge has to be set to a common applicable value
(2) The 5b or 8b Extended Tag capability is defined in the Device Capabi-
    lity register, and the 10b requester as well as completer is defined
    in the Device Capability 2 register
(3) The Extended Tag device policy would be overruled for any device if
    it does not match with its device capabilities register
(4) In case of multiple device policies, due to multiple devices under
    the root bridge, the lowest applicable value will be programmed for
    all the devices
(5) There is no Extended Tag disable state; hence the default would be
    5b or 8b depending upon device HW-state. The 10b requester is disabled
    by default; hence any device policy request of 10b shall lead to 10b
    Requester enable state from root bridge to all end devices; if all the
    devices support 10b Requester as well as the completer capability. In
    this scenario, the default state of 5b/8b Extended Tag state in Device
    Control register is ignored as 10b capable devices should be able to
    handle lower size Extended Tag packet IDs autonomously.

This programming of Extended Tag, gets the device-specific platform policy
using the new PCI Express Platform Protocol interface (ECR version 0.8),
defined in the below feature request:-
  https://bugzilla.tianocore.org/show_bug.cgi?id=1954

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 | 278 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h |  50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  |  15 ++++++++++++++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h  |   4 ++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c |  36 ++++++++++++++++++++++++++++++++++++
 6 files changed, 383 insertions(+), 1 deletion(-)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index 7e43a26..6a6f648 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -297,6 +297,7 @@ struct _PCI_IO_DEVICE {
   PCI_FEATURE_POLICY                        SetupCTO;
   EFI_PCI_EXPRESS_ATOMIC_OP                 SetupAtomicOp;
   BOOLEAN                                   SetupLtr;
+  UINT8                                     SetupExtTag;
 };
 
 #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 63a243b..eaef3d3 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
@@ -1240,3 +1240,281 @@ ProgramLtr (
   return Status;
 }
 
+/**
+  The main routine to setup the PCI Express feature Extended Tag as per the
+  device-specific platform policy, as well as in complaince with the PCI Express
+  Base specification Revision 5.
+
+  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
+  @param PciExpressConfigurationTable  pointer to PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
+
+  @retval EFI_SUCCESS                   setup of PCI feature LTR is successful.
+**/
+EFI_STATUS
+SetupExtTag (
+  IN  PCI_IO_DEVICE                             *PciDevice,
+  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciExpressConfigurationTable
+  )
+{
+  PCI_REG_PCIE_DEVICE_CAPABILITY2 DeviceCap2;
+  PCI_REG_PCIE_DEVICE_CAPABILITY  DeviceCap;
+  EFI_PCI_EXPRESS_EXTENDED_TAG    PciExpressExtendedTag;
+
+  DeviceCap.Uint32 = PciDevice->PciExpressCapabilityStructure.DeviceCapability.Uint32;
+  DeviceCap2.Uint32 = PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Uint32;
+  //
+  // The PCI Express feature Extended Tag has to be maintained common from a
+  // root bridge device to all its child devices.
+  // The Device Capability 2 register is used to determine the 10b Extended Tag
+  // capability of a device. The device capability register is used to determine
+  // 5b/8b Extended Tag capability of a device
+  //
+  if (DeviceCap2.Bits.TenBitTagCompleterSupported & DeviceCap2.Bits.TenBitTagRequesterSupported) {
+    //
+    // device supports the 10b Extended Tag capability
+    //
+    PciExpressExtendedTag = EFI_PCI_EXPRESS_EXTENDED_TAG_10BIT;
+  } else {
+    if (DeviceCap.Bits.ExtendedTagField) {
+      PciExpressExtendedTag = EFI_PCI_EXPRESS_EXTENDED_TAG_8BIT;
+    } else {
+      PciExpressExtendedTag = EFI_PCI_EXPRESS_EXTENDED_TAG_5BIT;
+    }
+  }
+  if (PciDevice->SetupExtTag == EFI_PCI_EXPRESS_EXTENDED_TAG_AUTO) {
+    PciDevice->SetupExtTag = PciExpressExtendedTag;
+  }
+  //
+  // in case of PCI Bridge and its child devices
+  //
+  if (PciExpressConfigurationTable) {
+    //
+    // align the Extended Tag value as per the device supported value
+    //
+    PciExpressConfigurationTable->ExtendedTag = MIN (
+                                                  PciExpressExtendedTag,
+                                                  PciExpressConfigurationTable->ExtendedTag
+                                                  );
+    //
+    // check for any invalid platform policy request for the device; if true than
+    // align with the device capability value. Else align as per platform request
+    //
+    if (PciDevice->SetupExtTag > PciExpressConfigurationTable->ExtendedTag) {
+      //
+      // setup the device Extended Tag to common value supported by all the devices
+      //
+      PciDevice->SetupExtTag = PciExpressConfigurationTable->ExtendedTag;
+    }
+    //
+    // if the platform policy is to downgrade the device's Extended Tag value than
+    // all the other devices in the PCI tree including the root bridge will be align
+    // with this device override value
+    //
+    if (PciDevice->SetupExtTag < PciExpressConfigurationTable->ExtendedTag) {
+      PciExpressConfigurationTable->ExtendedTag = PciDevice->SetupExtTag;
+    }
+  } else {
+    //
+    // in case of RCiEP devices or the bridge device without any child, overrule
+    // the Extended Tag device policy if it does not match with its capability
+    //
+    PciDevice->SetupExtTag = MIN (
+                              PciDevice->SetupExtTag,
+                              PciExpressExtendedTag
+                              );
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "ExtTag: %d [cap:%d],",
+    PciDevice->SetupExtTag,
+    PciExpressExtendedTag
+    ));
+  return EFI_SUCCESS;
+}
+
+/**
+  Additional routine to setup the PCI Express feature Extended Tag in complaince
+  with the PCI Express Base specification Revision, a common value for all the
+  devices in the PCI hierarchy.
+
+  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
+  @param PciExpressConfigurationTable  pointer to PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
+
+  @retval EFI_SUCCESS                   setup of PCI feature LTR is successful.
+**/
+EFI_STATUS
+AlignExtTag (
+  IN  PCI_IO_DEVICE                             *PciDevice,
+  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciExpressConfigurationTable
+  )
+{
+  if (PciExpressConfigurationTable) {
+    //
+    // align the Extended Tag value to a common value among all the devices
+    //
+    PciDevice->SetupExtTag = MIN (
+                              PciDevice->SetupExtTag,
+                              PciExpressConfigurationTable->ExtendedTag
+                              );
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "ExtTag: %d,",
+    PciDevice->SetupExtTag
+    ));
+  return EFI_SUCCESS;
+}
+
+/**
+  Program the PCI Device Control 2 register for 10b Extended Tag value, or the
+  Device Control register for 5b/8b Extended Tag 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
+ProgramExtTag (
+  IN PCI_IO_DEVICE          *PciDevice,
+  IN VOID                   *PciExFeatureConfiguration
+  )
+{
+  PCI_REG_PCIE_DEVICE_CONTROL   DevCtl;
+  PCI_REG_PCIE_DEVICE_CONTROL2  DevCtl2;
+  UINT32                        Offset;
+  UINT32                        Offset2;
+  BOOLEAN                       OverrideDevCtl;
+  BOOLEAN                       OverrideDevCtl2;
+  EFI_STATUS                    Status;
+  EFI_TPL                       OldTpl;
+
+  //
+  // read the Device Control register for the Extended Tag Field Enable
+  //
+  DevCtl.Uint16 = 0;
+  Offset = PciDevice->PciExpressCapabilityOffset +
+              OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint16,
+                                  Offset,
+                                  1,
+                                  &DevCtl.Uint16
+                                  );
+  ASSERT (Status == EFI_SUCCESS);
+
+  OverrideDevCtl = FALSE;
+  //
+  // read the Device COntrol 2 register for the 10-Bit Tag Requester Enable
+  //
+  DevCtl2.Uint16 = 0;
+  Offset2 = PciDevice->PciExpressCapabilityOffset +
+              OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2);
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint16,
+                                  Offset2,
+                                  1,
+                                  &DevCtl2.Uint16
+                                  );
+  ASSERT (Status == EFI_SUCCESS);
+
+  OverrideDevCtl2 = FALSE;
+
+  if (PciDevice->SetupExtTag == EFI_PCI_EXPRESS_EXTENDED_TAG_5BIT) {
+    if (DevCtl.Bits.ExtendedTagField) {
+      DevCtl.Bits.ExtendedTagField = 0;
+      OverrideDevCtl = TRUE;
+    }
+
+    if (DevCtl2.Bits.TenBitTagRequesterEnable) {
+      DevCtl2.Bits.TenBitTagRequesterEnable = 0;
+      OverrideDevCtl2 = TRUE;
+    }
+  }
+  if (PciDevice->SetupExtTag == EFI_PCI_EXPRESS_EXTENDED_TAG_8BIT) {
+    if (!DevCtl.Bits.ExtendedTagField) {
+      DevCtl.Bits.ExtendedTagField = 1;
+      OverrideDevCtl = TRUE;
+    }
+    if (DevCtl2.Bits.TenBitTagRequesterEnable) {
+      DevCtl2.Bits.TenBitTagRequesterEnable = 0;
+      OverrideDevCtl2 = TRUE;
+    }
+  }
+  if (PciDevice->SetupExtTag == EFI_PCI_EXPRESS_EXTENDED_TAG_10BIT) {
+    if (!DevCtl2.Bits.TenBitTagRequesterEnable) {
+      DevCtl2.Bits.TenBitTagRequesterEnable = 1;
+      OverrideDevCtl2 = TRUE;
+    }
+  }
+
+  if (OverrideDevCtl) {
+
+    DEBUG (( DEBUG_INFO, "ExtTag=%d,", DevCtl.Bits.ExtendedTagField));
+
+    //
+    // 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,
+                                    &DevCtl.Uint16
+                                    );
+    //
+    // Restore TPL to its original level
+    //
+    gBS->RestoreTPL (OldTpl);
+
+    if (!EFI_ERROR(Status)) {
+      PciDevice->PciExpressCapabilityStructure.DeviceControl.Uint16 = DevCtl.Uint16;
+    } else {
+      ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, Offset);
+    }
+  } else {
+    DEBUG (( DEBUG_INFO, "no ExtTag (%d),", DevCtl.Bits.ExtendedTagField));
+  }
+
+  if (OverrideDevCtl2) {
+
+    DEBUG (( DEBUG_INFO, "10bExtTag=%d,", DevCtl2.Bits.TenBitTagRequesterEnable));
+
+    //
+    // 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,
+                                    Offset2,
+                                    1,
+                                    &DevCtl2.Uint16
+                                    );
+    //
+    // Restore TPL to its original level
+    //
+    gBS->RestoreTPL (OldTpl);
+
+    if (!EFI_ERROR(Status)) {
+      PciDevice->PciExpressCapabilityStructure.DeviceControl2.Uint16 = DevCtl2.Uint16;
+    } else {
+      ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, Offset2);
+    }
+  } else {
+    DEBUG (( DEBUG_INFO, "no 10bExtTag (%d),", DevCtl2.Bits.TenBitTagRequesterEnable));
+  }
+
+  return Status;
+}
+
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
index 374fe49..1cfca54 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
@@ -243,4 +243,54 @@ ProgramLtr (
   IN VOID                   *PciExFeatureConfiguration
   );
 
+/**
+  The main routine to setup the PCI Express feature Extended Tag as per the
+  device-specific platform policy, as well as in complaince with the PCI Express
+  Base specification Revision 5.
+
+  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
+  @param PciFeaturesConfigurationTable  pointer to PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
+
+  @retval EFI_SUCCESS                   setup of PCI feature LTR is successful.
+**/
+EFI_STATUS
+SetupExtTag (
+  IN  PCI_IO_DEVICE                             *PciDevice,
+  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciFeaturesConfigurationTable
+  );
+
+/**
+  Additional routine to setup the PCI Express feature Extended Tag in complaince
+  with the PCI Express Base specification Revision, a common value for all the
+  devices in the PCI hierarchy.
+
+  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
+  @param PciFeaturesConfigurationTable  pointer to PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
+
+  @retval EFI_SUCCESS                   setup of PCI feature LTR is successful.
+**/
+EFI_STATUS
+AlignExtTag (
+  IN  PCI_IO_DEVICE                             *PciDevice,
+  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciFeaturesConfigurationTable
+  );
+
+/**
+  Program the PCI Device Control 2 register for 10b Extended Tag value, or the
+  Device Control register for 5b/8b Extended Tag 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
+ProgramExtTag (
+  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 bdeb0d2..58d3780 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -38,7 +38,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY             mPciExpressPlatformPolicy = {
     //
     // support for PCI Express feature - Extended Tag
     //
-    FALSE,
+    TRUE,
     //
     // support for PCI Express feature - Relax Order
     //
@@ -140,6 +140,15 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT  mPciExpressFeatureInitializationList[]
   },
   {
     PciExpressFeatureProgramPhase,        PciExpressLtr,        ProgramLtr
+  },
+  {
+    PciExpressFeatureSetupPhase,          PciExpressExtTag,     SetupExtTag
+  },
+  {
+    PciExpressFeatureEntendedSetupPhase,  PciExpressExtTag,     AlignExtTag
+  },
+  {
+    PciExpressFeatureProgramPhase,        PciExpressExtTag,     ProgramExtTag
   }
 };
 
@@ -675,6 +684,10 @@ CreatePciRootBridgeDeviceNode (
     // tree
     //
     PciConfigTable->AtomicOpRoutingSupported    = TRUE;
+    //
+    // start by assuming the Extended Tag is 10b Requester capable
+    //
+    PciConfigTable->ExtendedTag                 = EFI_PCI_EXPRESS_EXTENDED_TAG_10BIT;
   }
 
   RootBridgeNode->PciExFeaturesConfigurationTable  = PciConfigTable;
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
index 5dded7c..c7cc7e5 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
@@ -94,6 +94,10 @@ struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE {
   // the AtomicOp of the EP device
   //
   BOOLEAN                                   AtomicOpRoutingSupported;
+  //
+  // to configure a common extended tag size for all the childs of a root port
+  //
+  UINT8                                     ExtendedTag;
 };
 
 //
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
index 83b3aa7..98d9875 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
@@ -368,6 +368,12 @@ SetupDefaultPciExpressDevicePolicy (
 
   PciDevice->SetupLtr = FALSE;
 
+  if (mPciExpressPlatformPolicy.ExtTag) {
+    PciDevice->SetupExtTag = EFI_PCI_EXPRESS_EXTENDED_TAG_AUTO;
+  } else {
+    PciDevice->SetupExtTag = EFI_PCI_EXPRESS_NOT_APPLICABLE;
+  }
+
 }
 
 /**
@@ -502,6 +508,15 @@ GetPciExpressDevicePolicy (
       PciDevice->SetupLtr = FALSE;
     }
 
+    //
+    // set the device-specifci policy for the PCI Express feature Extended Tag
+    //
+    if (mPciExpressPlatformPolicy.ExtTag) {
+      PciDevice->SetupExtTag = PciExpressDevicePolicy.DeviceCtlExtTag;
+    } else {
+      PciDevice->SetupExtTag = EFI_PCI_EXPRESS_NOT_APPLICABLE;
+    }
+
 
     DEBUG ((
       DEBUG_INFO,
@@ -668,6 +683,19 @@ GetPciExpressCto (
   return EFI_PCI_EXPRESS_NOT_APPLICABLE;
 }
 
+EFI_PCI_EXPRESS_EXTENDED_TAG
+GetPciExpressExtTag (
+  IN PCI_IO_DEVICE                        *PciDevice
+  )
+{
+  if (PciDevice->PciExpressCapabilityStructure.DeviceControl2.Bits.TenBitTagRequesterEnable) {
+    return EFI_PCI_EXPRESS_EXTENDED_TAG_10BIT;
+  } else if (PciDevice->PciExpressCapabilityStructure.DeviceControl.Bits.ExtendedTagField) {
+    return EFI_PCI_EXPRESS_EXTENDED_TAG_8BIT;
+  } else {
+    return EFI_PCI_EXPRESS_EXTENDED_TAG_5BIT;
+  }
+}
 
 /**
   Notifies the platform about the current PCI Express state of the device.
@@ -768,6 +796,14 @@ PciExpressPlatformNotifyDeviceState (
     PciExDeviceConfiguration.DeviceCtl2LTR = EFI_PCI_EXPRESS_NOT_APPLICABLE;
   }
 
+  //
+  // get the device-specific state for the PCie Extended Tag in the function
+  //
+  if (mPciExpressPlatformPolicy.ExtTag) {
+    PciExDeviceConfiguration.DeviceCtlExtTag = GetPciExpressExtTag (PciDevice);
+  } else {
+    PciExDeviceConfiguration.DeviceCtlExtTag = EFI_PCI_EXPRESS_NOT_APPLICABLE;
+  }
 
   if (mPciExPlatformProtocol != NULL) {
     return mPciExPlatformProtocol->NotifyDeviceState (
-- 
2.21.0.windows.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 11/12] PciBusDxe: New PCI Express feature ASPM support
  2020-02-07 20:04 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] PciBusDxe: New PCI Express features Javeed, Ashraf
                   ` (9 preceding siblings ...)
  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 ` 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
                   ` (13 subsequent siblings)
  24 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:04 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2500

This code change is to enable the common ASPM state for all the connected
devices, as per the PCI Express Base Specification 5, Revision 1.
This feature is not applicable to RCiEP, and to a vacant bridge device.
The device policy request from platform is applied if that is applicable
as per its Link Capability register. Since all the connected devices have
to have common applicable ASPM value, it would be overuled as per PCI Ex-
press Base Specification.
The device L0s/L1 Acceptance Latency is used to measure against the L0s/L1
Exit Latencies comprising from Root Bridge to all its EP devices. If not
applicable ASPM would be disabled for all the devices.

This programming of ASPM, gets the device-specific platform policy
using the new PCI Express Platform Protocol interface (ECR version 0.8),
defined in the below feature request:-
  https://bugzilla.tianocore.org/show_bug.cgi?id=1954

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 | 391 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h |  52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  |  23 ++++++++++++++++++++++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h  |  14 ++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c |  45 +++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 525 insertions(+), 1 deletion(-)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index 6a6f648..b5caffe 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -298,6 +298,7 @@ struct _PCI_IO_DEVICE {
   EFI_PCI_EXPRESS_ATOMIC_OP                 SetupAtomicOp;
   BOOLEAN                                   SetupLtr;
   UINT8                                     SetupExtTag;
+  UINT8                                     SetupAspm;
 };
 
 #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 eaef3d3..5e350e7 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
@@ -1518,3 +1518,394 @@ ProgramExtTag (
   return Status;
 }
 
+/**
+  Set the ASPM device policy as per the device's link capability.
+**/
+UINT8
+SetAspmPolicy (
+  IN UINT8  PciExpressLinkCapAspm
+  )
+{
+  switch (PciExpressLinkCapAspm) {
+    case 0:
+      //
+      // cannot support ASPM state, disable
+      //
+      return EFI_PCI_EXPRESS_ASPM_DISABLE;
+    case 1:
+      //
+      // supports only ASPM L0s state
+      //
+      return EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT;
+    case 2:
+      //
+      // supports only ASPM L1 state
+      //
+      return EFI_PCI_EXPRESS_ASPM_L1_SUPPORT;
+    case 3:
+      //
+      // supports both L0s and L1 ASPM states
+      //
+      return EFI_PCI_EXPRESS_ASPM_L0S_L1_SUPPORT;
+  }
+  return EFI_PCI_EXPRESS_ASPM_DISABLE;
+}
+
+/**
+  The main routine to setup the PCI Express feature ASPM as per the
+  device-specific platform policy, as well as in complaince with the PCI Express
+  Base specification Revision 5.
+
+  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
+  @param PciExpressConfigurationTable  pointer to PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
+
+  @retval EFI_SUCCESS                   setup of PCI feature LTR is successful.
+**/
+EFI_STATUS
+SetupAspm (
+  IN  PCI_IO_DEVICE                             *PciDevice,
+  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciExpressConfigurationTable
+  )
+{
+  PCI_REG_PCIE_LINK_CAPABILITY            PciExLinkCap;
+  PCI_REG_PCIE_DEVICE_CAPABILITY          PciExpressDeviceCapability;
+  BOOLEAN                                 AlignAspmPolicy;
+
+  PciExLinkCap.Uint32 = PciDevice->PciExpressCapabilityStructure.LinkCapability.Uint32;
+  PciExpressDeviceCapability.Uint32 = PciDevice->PciExpressCapabilityStructure.DeviceCapability.Uint32;
+  //
+  // ASPM support is only applicable to root bridge and its child devices. Not
+  // applicable to empty bridge devices or RCiEP devices
+  //
+  if (PciExpressConfigurationTable) {
+    PciExpressConfigurationTable->L0sExitLatency = MAX (
+                    PciExpressConfigurationTable->L0sExitLatency,
+                    (UINT8)PciExLinkCap.Bits.L0sExitLatency
+                    );
+    PciExpressConfigurationTable->L1ExitLatency = MAX (
+                    PciExpressConfigurationTable->L1ExitLatency,
+                    (UINT8)PciExLinkCap.Bits.L1ExitLatency
+                    );
+    if (PciDevice->SetupAspm == EFI_PCI_EXPRESS_ASPM_AUTO) {
+      //
+      // set the ASPM support as per device's link capability
+      //
+      PciDevice->SetupAspm = SetAspmPolicy ((UINT8)PciExLinkCap.Bits.Aspm);
+    } else {
+      //
+      // Check the ASPM device policy is applicable to the link capability.
+      // In case of invalid device policy, there are 2 options:
+      // (1) ASPM disable -> platform request rightly denied, and no ASPM
+      // (2) set as per the device capability -> platform request rightly denied,
+      //      but still set applicable power management
+      // this implementation shall take option 2 to overule invalid platform request
+      // and go with applicable policy as per device capability
+      //
+      switch (SetAspmPolicy ((UINT8)PciExLinkCap.Bits.Aspm)) {
+        case EFI_PCI_EXPRESS_ASPM_DISABLE:
+          PciDevice->SetupAspm = EFI_PCI_EXPRESS_ASPM_DISABLE;
+          break;
+        case EFI_PCI_EXPRESS_ASPM_L1_SUPPORT:
+          if (PciDevice->SetupAspm == EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT) {
+            //
+            // not applicable, set as per device's link capability
+            //
+            PciDevice->SetupAspm = EFI_PCI_EXPRESS_ASPM_L1_SUPPORT;
+          }
+          break;
+        case EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT:
+          if (PciDevice->SetupAspm == EFI_PCI_EXPRESS_ASPM_L1_SUPPORT) {
+            //
+            // not applicable, set as per device's link capability
+            //
+            PciDevice->SetupAspm = EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT;
+          }
+          break;
+      }
+    }
+    //
+    // set the ASPM policy to minimum state among all the devices links
+    //
+    PciExpressConfigurationTable->AspmSupport = MIN (
+                                                  PciExpressConfigurationTable->AspmSupport,
+                                                  PciDevice->SetupAspm
+                                                  );
+    //
+    // check the common ASPM value applicable as per this device capability, if
+    // not applicable disable the ASPM for all the devices
+    //
+    if (
+      (PciExpressConfigurationTable->AspmSupport == EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT
+        && SetAspmPolicy ((UINT8)PciExLinkCap.Bits.Aspm) == EFI_PCI_EXPRESS_ASPM_L1_SUPPORT)
+      ||
+      (PciExpressConfigurationTable->AspmSupport == EFI_PCI_EXPRESS_ASPM_L1_SUPPORT
+        && SetAspmPolicy ((UINT8)PciExLinkCap.Bits.Aspm) == EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT)
+      ) {
+      //
+      // disable the ASPM
+      //
+      PciExpressConfigurationTable->AspmSupport = EFI_PCI_EXPRESS_ASPM_DISABLE;
+      PciDevice->SetupAspm = PciExpressConfigurationTable->AspmSupport;
+    }
+
+    if (PciExpressConfigurationTable->AspmSupport != EFI_PCI_EXPRESS_ASPM_DISABLE) {
+      //
+      // in case of ASPM policy is not to disable the ASPM support, check other
+      // condition of EP device L0s/L1 acceptance latency with the L0s/L1 exit
+      // latencies comprising from this endpoint all the way up to root complex
+      // root port, to determine whether the ASPM L0s/L1 entry can be used with
+      // no loss of performance
+      //
+      if (!IS_PCI_BRIDGE (&PciDevice->Pci)) {
+
+        switch (PciExpressConfigurationTable->AspmSupport) {
+          case EFI_PCI_EXPRESS_ASPM_L0S_L1_SUPPORT:
+            if (
+                PciExpressDeviceCapability.Bits.EndpointL0sAcceptableLatency >= PciExpressConfigurationTable->L0sExitLatency
+                && PciExpressDeviceCapability.Bits.EndpointL1AcceptableLatency >= PciExpressConfigurationTable->L1ExitLatency
+            ) {
+              //
+              // both the L0s & L1 acceptance of this endpoint device is greater
+              // than or equal to all of the comprised L0s & L1 exit latencies
+              // thus good to set the ASPM to L0s & L1 state
+              //
+              AlignAspmPolicy = TRUE;
+            } else {
+              //
+              // in case the EP device L0s and L1 Acceptance latency does not match
+              // with the comprised L0s & L1 exit latencies than disable the ASPM
+              // state
+              //
+              AlignAspmPolicy = FALSE;
+            }
+            break;
+
+          case EFI_PCI_EXPRESS_ASPM_L1_SUPPORT:
+            if (
+                PciExpressDeviceCapability.Bits.EndpointL1AcceptableLatency >= PciExpressConfigurationTable->L1ExitLatency
+            ) {
+              //
+              // the endpoint device L1 acceptance latency meets the all the
+              // comprised L1 exit latencies of all the devices from the bridge
+              // hence ASPM L1 is applicable state for the PCI tree
+              //
+              AlignAspmPolicy = TRUE;
+            } else {
+              //
+              // in case the EP device L1 Acceptance latency does not match
+              // with the comprised L1 exit latencies than disable the ASPM
+              // state
+              //
+              AlignAspmPolicy = FALSE;
+            }
+            break;
+
+          case EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT:
+            if (
+                PciExpressDeviceCapability.Bits.EndpointL0sAcceptableLatency >= PciExpressConfigurationTable->L0sExitLatency
+            ) {
+              //
+              // the endpoint device L0s acceptance latency meets the all the
+              // comprised L0s exit latencies of all the devices from the bridge
+              // hence ASPM L0s is applicable state for the PCI tree
+              //
+              AlignAspmPolicy = TRUE;
+            } else {
+              //
+              // in case the EP device L0s Acceptance latency does not match
+              // with the comprised L0s exit latencies than disable the ASPM
+              // state
+              //
+              AlignAspmPolicy = FALSE;
+            }
+            break;
+        }
+      } else {
+        //
+        // align the bridge with the global common ASPM value
+        //
+        AlignAspmPolicy = TRUE;
+      }
+    } else {
+      //
+      // ASPM is disabled for all the devices
+      //
+      AlignAspmPolicy = FALSE;
+    }
+
+    if (AlignAspmPolicy) {
+      //
+      // reset the device's ASPM policy to common minimum value
+      //
+      if (PciDevice->SetupAspm != PciExpressConfigurationTable->AspmSupport) {
+        PciDevice->SetupAspm = PciExpressConfigurationTable->AspmSupport;
+      }
+    } else {
+      //
+      // disable the ASPM
+      //
+      PciExpressConfigurationTable->AspmSupport = EFI_PCI_EXPRESS_ASPM_DISABLE;
+      PciDevice->SetupAspm = PciExpressConfigurationTable->AspmSupport;
+    }
+    DEBUG ((
+      DEBUG_INFO,
+      "Aspm: %d [cap:%d],",
+      PciDevice->SetupAspm,
+      (PciExLinkCap.Bits.Aspm + 1)
+      ));
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Setup of PCI Express feature ASPM in the PciExpressFeatureEntendedSetupPhase
+**/
+EFI_STATUS
+AlignAspm (
+  IN  PCI_IO_DEVICE                             *PciDevice,
+  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciExpressConfigurationTable
+  )
+{
+  //
+  // ASPM support is only applicable to root bridge and its child devices. Not
+  // applicable to empty bridge devices or RCiEP devices
+  //
+  if (PciExpressConfigurationTable) {
+    //
+    // reset the device's ASPM policy to common minimum ASPM value
+    //
+    if (PciDevice->SetupAspm != PciExpressConfigurationTable->AspmSupport) {
+      PciDevice->SetupAspm = PciExpressConfigurationTable->AspmSupport;
+    }
+    DEBUG ((
+      DEBUG_INFO,
+      "Aspm: %d,",
+      PciDevice->SetupAspm
+      ));
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Get the ASPM value from the ASPM device policy.
+**/
+UINT8
+GetAspmValue (
+  IN UINT8  AspmPolicy
+  )
+{
+  switch (AspmPolicy) {
+    case EFI_PCI_EXPRESS_ASPM_DISABLE:
+      //
+      // ASPM disable
+      //
+      return 0;
+    case EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT:
+      //
+      // ASPM L0s state
+      //
+      return 1;
+    case EFI_PCI_EXPRESS_ASPM_L1_SUPPORT:
+      //
+      // ASPM L1 state
+      //
+      return 2;
+    case EFI_PCI_EXPRESS_ASPM_L0S_L1_SUPPORT:
+      //
+      // L0s and L1 ASPM states
+      //
+      return 3;
+  }
+  return 0;
+}
+
+/**
+  Program the PCIe Link Control register ASPM Control field; 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
+ProgramAspm (
+  IN PCI_IO_DEVICE          *PciDevice,
+  IN VOID                   *PciExFeatureConfiguration
+  )
+{
+  PCI_REG_PCIE_LINK_CONTROL     LinkCtl;
+  UINT32                        Offset;
+  EFI_STATUS                    Status;
+  EFI_TPL                       OldTpl;
+  UINT8                         AspmValue;
+
+  //
+  // ASPM support is only applicable to root bridge and its child devices. Not
+  // applicable to empty bridge devices or RCiEP devices
+  //
+  if (!PciExFeatureConfiguration) {
+    return EFI_SUCCESS;
+  }
+
+  //
+  // read the link Control register for the ASPM Control
+  //
+  LinkCtl.Uint16 = 0;
+  Offset = PciDevice->PciExpressCapabilityOffset +
+              OFFSET_OF (PCI_CAPABILITY_PCIEXP, LinkControl);
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint16,
+                                  Offset,
+                                  1,
+                                  &LinkCtl.Uint16
+                                  );
+  ASSERT (Status == EFI_SUCCESS);
+
+  AspmValue = GetAspmValue (PciDevice->SetupAspm);
+  if (AspmValue != LinkCtl.Bits.AspmControl) {
+    DEBUG ((
+      DEBUG_INFO,
+      "Aspm: %d,",
+      AspmValue
+      ));
+    //
+    // 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,
+                                    &LinkCtl.Uint16
+                                    );
+    //
+    // Restore TPL to its original level
+    //
+    gBS->RestoreTPL (OldTpl);
+
+    if (!EFI_ERROR (Status)) {
+      PciDevice->PciExpressCapabilityStructure.LinkControl.Uint16 = LinkCtl.Uint16;
+    } else {
+      ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, Offset);
+      return Status;
+    }
+  } else {
+    DEBUG ((
+      DEBUG_INFO,
+      "No Aspm (%d),",
+      AspmValue
+      ));
+  }
+  return EFI_SUCCESS;
+}
+
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
index 1cfca54..351c61e 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
@@ -9,6 +9,15 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #ifndef _EFI_PCI_EXPRESS_FEATURES_H_
 #define _EFI_PCI_EXPRESS_FEATURES_H_
 
+//
+// PCIe L0s Exit Latencies declarations
+//
+#define PCIE_LINK_CAPABILITY_L0S_EXIT_LATENCY_64NS  0   // less than 64ns
+
+//
+// PCIe L1 Exit latencies declarations
+//
+#define PCIE_LINK_CAPABILITY_L1_EXIT_LATENCY_1US    0   // less than 1us
 
 /**
   The main routine which process the PCI feature Max_Payload_Size as per the
@@ -293,4 +302,47 @@ ProgramExtTag (
   IN VOID                   *PciExFeatureConfiguration
   );
 
+/**
+  The main routine to setup the PCI Express feature ASPM as per the
+  device-specific platform policy, as well as in complaince with the PCI Express
+  Base specification Revision 5.
+
+  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
+  @param PciFeaturesConfigurationTable  pointer to PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
+
+  @retval EFI_SUCCESS                   setup of PCI feature LTR is successful.
+**/
+EFI_STATUS
+SetupAspm (
+  IN  PCI_IO_DEVICE                             *PciDevice,
+  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciFeaturesConfigurationTable
+  );
+
+/**
+  Setup of PCI Express feature ASPM in the PciExpressFeatureEntendedSetupPhase
+**/
+EFI_STATUS
+AlignAspm (
+  IN  PCI_IO_DEVICE                             *PciDevice,
+  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciFeaturesConfigurationTable
+  );
+
+/**
+  Program the PCIe Link Control register ASPM Control field; 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
+ProgramAspm (
+  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 58d3780..24781c6 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -50,7 +50,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY             mPciExpressPlatformPolicy = {
     //
     // support for PCI Express feature - ASPM state
     //
-    FALSE,
+    TRUE,
     //
     // support for PCI Express feature - Common Clock Configuration
     //
@@ -96,6 +96,15 @@ BOOLEAN   mPciExpressGetPlatformPolicyComplete = FALSE;
 //
 PCI_EXPRESS_FEATURE_INITIALIZATION_POINT  mPciExpressFeatureInitializationList[] = {
 
+  {
+    PciExpressFeatureSetupPhase,          PciExpressAspm,       SetupAspm
+  },
+  {
+    PciExpressFeatureEntendedSetupPhase,  PciExpressAspm,       AlignAspm
+  },
+  {
+    PciExpressFeatureProgramPhase,        PciExpressAspm,       ProgramAspm
+  },
   {
     PciExpressFeatureSetupPhase,          PciExpressMps,        SetupMaxPayloadSize
   },
@@ -688,6 +697,18 @@ CreatePciRootBridgeDeviceNode (
     // start by assuming the Extended Tag is 10b Requester capable
     //
     PciConfigTable->ExtendedTag                 = EFI_PCI_EXPRESS_EXTENDED_TAG_10BIT;
+    //
+    // initial state set to ASPM L0s and L1 both
+    //
+    PciConfigTable->AspmSupport                 = EFI_PCI_EXPRESS_ASPM_L0S_L1_SUPPORT;
+    //
+    // start by assuming less than 64ns of L0s Exit Latency
+    //
+    PciConfigTable->L0sExitLatency              = PCIE_LINK_CAPABILITY_L0S_EXIT_LATENCY_64NS;
+    //
+    // start by assuming less than 1us of L1 Exit Latency
+    //
+    PciConfigTable->L1ExitLatency               = PCIE_LINK_CAPABILITY_L1_EXIT_LATENCY_1US;
   }
 
   RootBridgeNode->PciExFeaturesConfigurationTable  = PciConfigTable;
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
index c7cc7e5..5e0f43b 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
@@ -98,6 +98,20 @@ struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE {
   // to configure a common extended tag size for all the childs of a root port
   //
   UINT8                                     ExtendedTag;
+  //
+  // to configure common ASPM state for all the devices link
+  //
+  UINT8                                     AspmSupport;
+  //
+  // to record maximum L0s Exit Latency among all the devices starting from root
+  // bridge device to its downstream bridge and its endpoint device
+  //
+  UINT8                                     L0sExitLatency;
+  //
+  // to record maximum L1 Exit Latency among all the devices starting from root
+  // bridge device to its downstream bridge and its endpoint device
+  //
+  UINT8                                     L1ExitLatency;
 };
 
 //
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
index 98d9875..f301557 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
@@ -374,6 +374,16 @@ SetupDefaultPciExpressDevicePolicy (
     PciDevice->SetupExtTag = EFI_PCI_EXPRESS_NOT_APPLICABLE;
   }
 
+  //
+  // default device policy for device's link ASPM
+  //
+  if (mPciExpressPlatformPolicy.Aspm) {
+    PciDevice->SetupAspm = EFI_PCI_EXPRESS_ASPM_AUTO;
+  } else {
+    PciDevice->SetupAspm = EFI_PCI_EXPRESS_NOT_APPLICABLE;
+  }
+
+
 }
 
 /**
@@ -517,6 +527,14 @@ GetPciExpressDevicePolicy (
       PciDevice->SetupExtTag = EFI_PCI_EXPRESS_NOT_APPLICABLE;
     }
 
+    //
+    // set the device-specific policy for the PCI Express feature ASPM
+    //
+    if (mPciExpressPlatformPolicy.Aspm) {
+      PciDevice->SetupAspm = PciExpressDevicePolicy.LinkCtlASPMState;
+    } else {
+      PciDevice->SetupAspm = EFI_PCI_EXPRESS_NOT_APPLICABLE;
+    }
 
     DEBUG ((
       DEBUG_INFO,
@@ -697,6 +715,24 @@ GetPciExpressExtTag (
   }
 }
 
+EFI_PCI_EXPRESS_ASPM_SUPPORT
+GetPciExpressAspmState (
+  IN PCI_IO_DEVICE                        *PciDevice
+  )
+{
+  switch (PciDevice->PciExpressCapabilityStructure.LinkControl.Bits.AspmControl) {
+    case 0:
+      return EFI_PCI_EXPRESS_ASPM_DISABLE;
+    case 1:
+      return EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT;
+    case 2:
+      return EFI_PCI_EXPRESS_ASPM_L1_SUPPORT;
+    case 3:
+      return EFI_PCI_EXPRESS_ASPM_L0S_L1_SUPPORT;
+  }
+  return EFI_PCI_EXPRESS_NOT_APPLICABLE;
+}
+
 /**
   Notifies the platform about the current PCI Express state of the device.
 
@@ -805,6 +841,15 @@ PciExpressPlatformNotifyDeviceState (
     PciExDeviceConfiguration.DeviceCtlExtTag = EFI_PCI_EXPRESS_NOT_APPLICABLE;
   }
 
+  //
+  // get the device-specific state for PCIe ASPM state
+  //
+  if (mPciExpressPlatformPolicy.Aspm) {
+    PciExDeviceConfiguration.LinkCtlASPMState = GetPciExpressAspmState (PciDevice);
+  } else {
+    PciExDeviceConfiguration.LinkCtlASPMState = EFI_PCI_EXPRESS_NOT_APPLICABLE;
+  }
+
   if (mPciExPlatformProtocol != NULL) {
     return mPciExPlatformProtocol->NotifyDeviceState (
                                     mPciExPlatformProtocol,
-- 
2.21.0.windows.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 12/12] PciBusDxe: New PCI Express feature Common CLock Config
  2020-02-07 20:04 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] PciBusDxe: New PCI Express features Javeed, Ashraf
                   ` (10 preceding siblings ...)
  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 ` Javeed, Ashraf
       [not found] ` <15F1377EA7D1AA4F.7869@groups.io>
                   ` (12 subsequent siblings)
  24 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:04 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2500

This code change enforces the Link Control register CCC field as per the
following conditions:-
(1) When the Clock Configuration device policy for all the devices are
    set to EFI_PCI_EXPRESS_CLK_CFG_AUTO:-
    - Based on the Link Status register's Slot Clock Configuration field,
      all the devices CCC value shall be aligned
(2) When the Clock Configuration device policy for one or more devices
    are either set to EFI_PCI_EXPRESS_CLK_CFG_ASYNCH or EFI_PCI_EXPRESS_
    CLK_CFG_COMMON
    - enforces the same clock configuration for all the devices from
      root bridge
Note that the recommendation to the platform is to always provide the
device policy as EFI_PCI_EXPRESS_CLK_CFG_AUTO.
In case for any device its Link Control register CCC field is required
to be changed based on its present HW-state, than Link Retraining is
preformed on the downstream ports as per the PCI Express Base
specification.

This programming of CCC, gets the device-specific platform policy
using the new PCI Express Platform Protocol interface (ECR version 0.8),
defined in the below feature request:-
  https://bugzilla.tianocore.org/show_bug.cgi?id=1954

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 | 267 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h |  51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  |  20 ++++++++++++++++++--
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h  |   9 +++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c |  28 ++++++++++++++++++++++++++++
 6 files changed, 374 insertions(+), 2 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index b5caffe..34f482d 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -299,6 +299,7 @@ struct _PCI_IO_DEVICE {
   BOOLEAN                                   SetupLtr;
   UINT8                                     SetupExtTag;
   UINT8                                     SetupAspm;
+  EFI_PCI_EXPRESS_COMMON_CLOCK_CFG          SetupCcc;
 };
 
 #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 5e350e7..1e2f4a4 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
@@ -1909,3 +1909,270 @@ ProgramAspm (
   return EFI_SUCCESS;
 }
 
+/**
+  The main routine to setup the PCI Express feature Common Clock configuration
+  as per the device-specific platform policy, as well as in complaince with the
+  PCI Express Base specification Revision 5.
+
+  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
+  @param PciExpressConfigurationTable  pointer to PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
+
+  @retval EFI_SUCCESS                   setup of PCI feature LTR is successful.
+**/
+EFI_STATUS
+SetupCommonClkCfg (
+  IN  PCI_IO_DEVICE                             *PciDevice,
+  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciExpressConfigurationTable
+  )
+{
+  PCI_REG_PCIE_LINK_STATUS                      LinkSts;
+
+  LinkSts.Uint16 = PciDevice->PciExpressCapabilityStructure.LinkStatus.Uint16;
+
+  //
+  // Common Clock Configuration is only applicable to root bridge and its child
+  // devices. Not applicable to empty bridge devices or RCiEP devices
+  //
+  if (PciExpressConfigurationTable) {
+    if (PciDevice->SetupCcc == EFI_PCI_EXPRESS_CLK_CFG_AUTO) {
+      //
+      // as per the PCI Express Base Specification, the link status register
+      // slot clock configuration of the opposing side of link devices indicate
+      // the clock configuration properly; hence rely on this data to configure
+      // the link's clock configuration
+      //
+      if (LinkSts.Bits.SlotClockConfiguration) {
+        PciExpressConfigurationTable->CommonClockConfiguration = TRUE;
+      } else {
+        PciExpressConfigurationTable->CommonClockConfiguration = FALSE;
+      }
+    } else if (PciDevice->SetupCcc == EFI_PCI_EXPRESS_CLK_CFG_ASYNCH) {
+      //
+      // platform override to any device shall change for other device on the
+      // link, the clock configuration has to be maintained common across all
+      // the devices
+      //
+      PciExpressConfigurationTable->CommonClockConfiguration = FALSE;
+    } else {
+      PciExpressConfigurationTable->CommonClockConfiguration = TRUE;
+    }
+  }
+  return EFI_SUCCESS;
+}
+
+/**
+  Program the PCIe Link Control register Coomon Clock Configuration field; 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
+ProgramCcc (
+  IN PCI_IO_DEVICE                            *PciDevice,
+  IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExFeatureConfiguration
+  )
+{
+  PCI_REG_PCIE_LINK_CONTROL     LinkCtl;
+  UINT32                        Offset;
+  EFI_STATUS                    Status;
+  EFI_TPL                       OldTpl;
+
+  //
+  // Common Clock Configuration is only applicable to root bridge and its child
+  // devices. Not applicable to empty bridge devices or RCiEP devices
+  //
+  if (!PciExFeatureConfiguration) {
+    return EFI_SUCCESS;
+  }
+
+  //
+  // read the link Control register for the ASPM Control
+  //
+  LinkCtl.Uint16 = 0;
+  Offset = PciDevice->PciExpressCapabilityOffset +
+              OFFSET_OF (PCI_CAPABILITY_PCIEXP, LinkControl);
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint16,
+                                  Offset,
+                                  1,
+                                  &LinkCtl.Uint16
+                                  );
+  ASSERT (Status == EFI_SUCCESS);
+
+  //
+  // in case Common Clock Configuration is required to be programmed in the
+  // downstream ports from the root bridge devices in the heirarchy
+  //
+  if (PciExFeatureConfiguration->CommonClockConfiguration == TRUE) {
+    if (LinkCtl.Bits.CommonClockConfiguration == 0) {
+      LinkCtl.Bits.CommonClockConfiguration = 1;
+      //
+      // current clock mode does not match hence retrain of the link at bridge device
+      // is required
+      //
+      PciExFeatureConfiguration->LinkReTrain = TRUE;
+    }
+  } else {
+    //
+    // in case the opposing devices of the PCI link have different reference clock
+    // set the link control register CCC field accordingly
+    //
+    if (LinkCtl.Bits.CommonClockConfiguration) {
+      LinkCtl.Bits.CommonClockConfiguration = 0;
+      //
+      // current clock mode does not match hence retrain of the link at bridge device
+      // is required
+      //
+      PciExFeatureConfiguration->LinkReTrain = TRUE;
+    }
+  }
+  //
+  // use the retrain flag as a sigm to also update the CCC of the link register
+  //
+  if (PciExFeatureConfiguration->LinkReTrain == TRUE) {
+    DEBUG ((
+      DEBUG_INFO,
+      "CCC: %d,",
+      LinkCtl.Bits.CommonClockConfiguration
+      ));
+    //
+    // 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,
+                                    &LinkCtl.Uint16
+                                    );
+    //
+    // Restore TPL to its original level
+    //
+    gBS->RestoreTPL (OldTpl);
+
+    if (!EFI_ERROR (Status)) {
+      PciDevice->PciExpressCapabilityStructure.LinkControl.Uint16 = LinkCtl.Uint16;
+    } else {
+      ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, Offset);
+      return Status;
+    }
+  } else {
+    PciDevice->PciExpressCapabilityStructure.LinkControl.Uint16 = LinkCtl.Uint16;
+    DEBUG ((
+      DEBUG_INFO,
+      "No CCC (%d),",
+      LinkCtl.Bits.CommonClockConfiguration
+      ));
+  }
+  return EFI_SUCCESS;
+}
+
+/**
+  Second phase of programming for Common Clock COnfiguration, conditoonally done
+  only on the downstream ports (bridge devices only).
+
+  @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
+EnforceCcc (
+  IN PCI_IO_DEVICE                            *PciDevice,
+  IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExFeatureConfiguration
+  )
+{
+  PCI_REG_PCIE_LINK_CONTROL     LinkCtl;
+  PCI_REG_PCIE_LINK_STATUS      LinkSts;
+  PCI_REG_PCIE_CAPABILITY       PciExCap;
+  UINT32                        Offset;
+  EFI_STATUS                    Status;
+  EFI_TPL                       OldTpl;
+
+  //
+  // Common Clock Configuration is only applicable to root bridge and its child
+  // devices. Not applicable to empty bridge devices or RCiEP devices
+  //
+  if (!PciExFeatureConfiguration) {
+    return EFI_SUCCESS;
+  }
+  PciExCap.Uint16 = PciDevice->PciExpressCapabilityStructure.Capability.Uint16;
+  LinkCtl.Uint16 = PciDevice->PciExpressCapabilityStructure.LinkControl.Uint16;
+
+  //
+  // retrain the bridge device (downstream ports including the root port)
+  //
+  if (PciExFeatureConfiguration->LinkReTrain == TRUE) {
+    if (IS_PCI_BRIDGE (&PciDevice->Pci)) {
+      //
+      // retrain of the PCI link happens for CCC change only on the downstream
+      // ports
+      //
+      if (
+        PciExCap.Bits.DevicePortType == PCIE_DEVICE_PORT_TYPE_ROOT_PORT
+        || PciExCap.Bits.DevicePortType == PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT
+        ) {
+        LinkCtl.Bits.RetrainLink = 1;
+        Offset = PciDevice->PciExpressCapabilityOffset +
+                     OFFSET_OF (PCI_CAPABILITY_PCIEXP, LinkControl);
+        //
+        // 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,
+                                        &LinkCtl.Uint16
+                                        );
+        //
+        // Restore TPL to its original level
+        //
+        gBS->RestoreTPL (OldTpl);
+
+        if (!EFI_ERROR (Status)) {
+          //
+          // poll the link status register for the link retrain to be complete
+          //
+          Offset = PciDevice->PciExpressCapabilityOffset +
+                               OFFSET_OF (PCI_CAPABILITY_PCIEXP, LinkStatus);
+          do {
+            Status = PciDevice->PciIo.Pci.Read (
+                                            &PciDevice->PciIo,
+                                            EfiPciIoWidthUint16,
+                                            Offset,
+                                            1,
+                                            &LinkSts.Uint16
+                                            );
+            ASSERT (Status == EFI_SUCCESS);
+          } while (LinkSts.Bits.LinkTraining);
+        } else {
+          ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, Offset);
+          return Status;
+        }
+      }
+      //
+      // ignore the upstream bridge devices
+      //
+    }
+    //
+    // not applicable to endpoint devices
+    //
+  }
+  return EFI_SUCCESS;
+}
+
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
index 351c61e..33df337 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
@@ -345,4 +345,55 @@ ProgramAspm (
   IN VOID                   *PciExFeatureConfiguration
   );
 
+/**
+  The main routine to setup the PCI Express feature Common Clock configuration
+  as per the device-specific platform policy, as well as in complaince with the
+  PCI Express Base specification Revision 5.
+
+  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
+  @param PciExpressConfigurationTable  pointer to PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
+
+  @retval EFI_SUCCESS                   setup of PCI feature LTR is successful.
+**/
+EFI_STATUS
+SetupCommonClkCfg (
+  IN  PCI_IO_DEVICE                             *PciDevice,
+  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciExpressConfigurationTable
+  );
+
+/**
+  Program the PCIe Link Control register Coomon Clock Configuration field; 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
+ProgramCcc (
+  IN PCI_IO_DEVICE                            *PciDevice,
+  IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExFeatureConfiguration
+  );
+
+/**
+  Second phase of programming for Common Clock COnfiguration, conditoonally done
+  only on the downstream ports (bridge devices only).
+
+  @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
+EnforceCcc (
+  IN PCI_IO_DEVICE                            *PciDevice,
+  IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExFeatureConfiguration
+  );
 #endif
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
index 24781c6..4d3641c 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -54,7 +54,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY             mPciExpressPlatformPolicy = {
     //
     // support for PCI Express feature - Common Clock Configuration
     //
-    FALSE,
+    TRUE,
     //
     // support for PCI Express feature - Extended Sync
     //
@@ -95,7 +95,15 @@ BOOLEAN   mPciExpressGetPlatformPolicyComplete = FALSE;
 // PCI Express feature initialization phase handle routines
 //
 PCI_EXPRESS_FEATURE_INITIALIZATION_POINT  mPciExpressFeatureInitializationList[] = {
-
+  {
+    PciExpressFeatureSetupPhase,          PciExpressCcc,        SetupCommonClkCfg
+  },
+  {
+    PciExpressFeatureEntendedSetupPhase,  PciExpressCcc,        ProgramCcc
+  },
+  {
+    PciExpressFeatureProgramPhase,        PciExpressCcc,        EnforceCcc
+  },
   {
     PciExpressFeatureSetupPhase,          PciExpressAspm,       SetupAspm
   },
@@ -709,6 +717,14 @@ CreatePciRootBridgeDeviceNode (
     // start by assuming less than 1us of L1 Exit Latency
     //
     PciConfigTable->L1ExitLatency               = PCIE_LINK_CAPABILITY_L1_EXIT_LATENCY_1US;
+    //
+    // default link retrain is not required
+    //
+    PciConfigTable->LinkReTrain                 = FALSE;
+    //
+    // start by assuming no common clock configuration mode for the device's link
+    //
+    PciConfigTable->CommonClockConfiguration    = FALSE;
   }
 
   RootBridgeNode->PciExFeaturesConfigurationTable  = PciConfigTable;
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
index 5e0f43b..481bd90 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
@@ -112,6 +112,15 @@ struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE {
   // bridge device to its downstream bridge and its endpoint device
   //
   UINT8                                     L1ExitLatency;
+  //
+  // flag to indicate the link training is required in the devices of downstream
+  // ports
+  //
+  BOOLEAN                                   LinkReTrain;
+  //
+  // link status slot clock configuration
+  //
+  BOOLEAN                                   CommonClockConfiguration;
 };
 
 //
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
index f301557..bf380ab 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
@@ -383,6 +383,14 @@ SetupDefaultPciExpressDevicePolicy (
     PciDevice->SetupAspm = EFI_PCI_EXPRESS_NOT_APPLICABLE;
   }
 
+  //
+  // default device policy for the device's link clock configuration
+  //
+  if (mPciExpressPlatformPolicy.Ccc) {
+    PciDevice->SetupCcc = EFI_PCI_EXPRESS_CLK_CFG_AUTO;
+  } else {
+    PciDevice->SetupCcc = EFI_PCI_EXPRESS_NOT_APPLICABLE;
+  }
 
 }
 
@@ -536,6 +544,15 @@ GetPciExpressDevicePolicy (
       PciDevice->SetupAspm = EFI_PCI_EXPRESS_NOT_APPLICABLE;
     }
 
+    //
+    // set the device policy for the PCI Express feature Common Clock Configuration
+    //
+    if (mPciExpressPlatformPolicy.Ccc) {
+      PciDevice->SetupCcc = PciExpressDevicePolicy.LinkCtlCommonClkCfg;
+    } else {
+      PciDevice->SetupCcc = EFI_PCI_EXPRESS_NOT_APPLICABLE;
+    }
+
     DEBUG ((
       DEBUG_INFO,
       "[device policy: platform]"
@@ -850,6 +867,17 @@ PciExpressPlatformNotifyDeviceState (
     PciExDeviceConfiguration.LinkCtlASPMState = EFI_PCI_EXPRESS_NOT_APPLICABLE;
   }
 
+  //
+  // get the device-specific Common CLock Configuration value
+  //
+  if (mPciExpressPlatformPolicy.Ccc) {
+    PciExDeviceConfiguration.LinkCtlCommonClkCfg =
+        PciDevice->PciExpressCapabilityStructure.LinkControl.Bits.CommonClockConfiguration ?
+            EFI_PCI_EXPRESS_CLK_CFG_COMMON : EFI_PCI_EXPRESS_CLK_CFG_ASYNCH;
+  } else {
+    PciExDeviceConfiguration.LinkCtlCommonClkCfg = EFI_PCI_EXPRESS_NOT_APPLICABLE;
+  }
+
   if (mPciExPlatformProtocol != NULL) {
     return mPciExPlatformProtocol->NotifyDeviceState (
                                     mPciExPlatformProtocol,
-- 
2.21.0.windows.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe: Setup for PCI Express features
       [not found] ` <15F1377EA7D1AA4F.7869@groups.io>
@ 2020-02-07 20:16   ` Javeed, Ashraf
  2020-02-10  7:20     ` Ni, Ray
  0 siblings, 1 reply; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:16 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch can also be viewed in the following repo:-
https://github.com/ashrafj/edk2-staging/commit/9d9f47b271f2c8fe7f7fa2a72bc98db3c28b3312

Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Saturday, February 8, 2020 1:35 AM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12]
> MdeModulePkg/PciBusDxe: Setup for PCI Express features
> 
> References:-
>   https://bugzilla.tianocore.org/show_bug.cgi?id=1954
>   https://bugzilla.tianocore.org/show_bug.cgi?id=2194
>   https://bugzilla.tianocore.org/show_bug.cgi?id=2313
>   https://bugzilla.tianocore.org/show_bug.cgi?id=2499
>   https://bugzilla.tianocore.org/show_bug.cgi?id=2500
> 
> This code change represents the preparation of common code setup for the
> new PCI Express features initialization, utilizing the new PCI Express
> Platform / Override Protocol.
> The new set of source files are as follows:-
>   new file:   /PciFeatureSupport.c
>   new file:   /PciFeatureSupport.h
>   new file:   /PciPlatformSupport.c
>   new file:   /PciPlatformSupport.h
> 
> 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.c               |   6 +++++-
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h               |  12 ++++++++++--
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf          |   9 ++++++++-
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c |  12
> +++++++++++-
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c    | 891
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h    | 226
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c   | 302
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h   |  87
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++
>  8 files changed, 1540 insertions(+), 5 deletions(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> index b020ce5..714101c 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> @@ -8,7 +8,7 @@
>    PCI Root Bridges. So it means platform needs install PCI Root Bridge IO
> protocol for each
>    PCI Root Bus and install PCI Host Bridge Resource Allocation Protocol.
> 
> -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> @@ -284,6 +284,10 @@ PciBusDriverBindingStart (
>            (VOID **) &gPciOverrideProtocol
>            );
>    }
> +  //
> +  // get the PCI Express Protocol or the PCI Express Override Protocol
> +  //
> +  GetPciExpressProtocol ();
> 
>    if (mIoMmuProtocol == NULL) {
>      gBS->LocateProtocol (
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> index 504a1b1..225229d 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> @@ -1,7 +1,7 @@
>  /** @file
>    Header files and data structures needed by PCI Bus module.
> 
> -Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  **/
> @@ -42,6 +42,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
>  #include <IndustryStandard/Pci.h>
>  #include <IndustryStandard/PeImage.h>
>  #include <IndustryStandard/Acpi.h>
> +#include <Protocol/PciExpressOverride.h>
> +#include <Protocol/PciExpressPlatform.h>
> 
>  typedef struct _PCI_IO_DEVICE              PCI_IO_DEVICE;
>  typedef struct _PCI_BAR                    PCI_BAR;
> @@ -79,6 +81,8 @@ typedef enum {
>  #include "PciPowerManagement.h"
>  #include "PciHotPlugSupport.h"
>  #include "PciLib.h"
> +#include "PciPlatformSupport.h"
> +#include "PciFeatureSupport.h"
> 
>  #define VGABASE1  0x3B0
>  #define VGALIMIT1 0x3BB
> @@ -263,9 +267,13 @@ struct _PCI_IO_DEVICE {
> 
>    BOOLEAN                                   IsPciExp;
>    //
> -  // For SR-IOV
> +  // For PCI Express Capability List Structure
>    //
>    UINT8                                     PciExpressCapabilityOffset;
> +  PCI_CAPABILITY_PCIEXP                     PciExpressCapabilityStructure;
> +  //
> +  // For SR-IOV
> +  //
>    UINT32                                    AriCapabilityOffset;
>    UINT32                                    SrIovCapabilityOffset;
>    UINT32                                    MrIovCapabilityOffset;
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> index 05c2202..f06b411 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> @@ -2,7 +2,7 @@
>  #  The PCI bus driver will probe all PCI devices and allocate MMIO and IO space
> for these devices.
>  #  Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable hot
> plug supporting.
>  #
> -#  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
> +#  Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
>  #
>  #  SPDX-License-Identifier: BSD-2-Clause-Patent
>  #
> @@ -57,6 +57,10 @@
>    PciCommand.h
>    PciIo.h
>    PciBus.h
> +  PciFeatureSupport.c
> +  PciFeatureSupport.h
> +  PciPlatformSupport.c
> +  PciPlatformSupport.h
> 
>  [Packages]
>    MdePkg/MdePkg.dec
> @@ -91,6 +95,9 @@
>    gEfiLoadFile2ProtocolGuid                       ## SOMETIMES_PRODUCES
>    gEdkiiIoMmuProtocolGuid                         ## SOMETIMES_CONSUMES
>    gEfiLoadedImageDevicePathProtocolGuid           ## CONSUMES
> +  gEfiPciExpressPlatformProtocolGuid                     ## SOMETIMES_CONSUMES
> +  gEfiPciExpressOverrideProtocolGuid                     ## SOMETIMES_CONSUMES
> +
> 
>  [FeaturePcd]
>    gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport      ##
> CONSUMES
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> index c7eafff..c9e52ea 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> @@ -1,7 +1,7 @@
>  /** @file
>    PCI emumeration support functions implementation for PCI Bus module.
> 
> -Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
>  (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> @@ -2154,6 +2154,16 @@ CreatePciIoDevice (
>               );
>    if (!EFI_ERROR (Status)) {
>      PciIoDevice->IsPciExp = TRUE;
> +    //
> +    // read the PCI device's entire PCI Express Capability structure
> +    //
> +    PciIo->Pci.Read (
> +                  PciIo,
> +                  EfiPciIoWidthUint8,
> +                  PciIoDevice->PciExpressCapabilityOffset,
> +                  sizeof (PCI_CAPABILITY_PCIEXP) / sizeof (UINT8),
> +                  &PciIoDevice->PciExpressCapabilityStructure
> +                  );
>    }
> 
>    if (PcdGetBool (PcdAriSupport)) {
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> new file mode 100644
> index 0000000..3980a8e
> --- /dev/null
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> @@ -0,0 +1,891 @@
> +/** @file
> +  PCI standard feature support functions implementation for PCI Bus module..
> +
> +Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "PciBus.h"
> +#include "PciFeatureSupport.h"
> +
> +/**
> +  Hold the current instance of Root Bridge IO protocol Handle
> +**/
> +EFI_HANDLE                                  mRootBridgeHandle;
> +
> +/**
> +  A gobal pointer to BRIDGE_DEVICE_NODE buffer to track all the primary
> physical
> +  PCI Root Ports (PCI Controllers) for a given PCI Root Bridge instance while
> +  enumerating to configure the PCI features
> +**/
> +LIST_ENTRY                                  mRootBridgeDeviceList;
> +
> +/**
> + global list to indicate the supported PCI Express features of this driver, it
> + is expected to be overridden based on the platform request
> +**/
> +EFI_PCI_EXPRESS_PLATFORM_POLICY             mPciExpressPlatformPolicy = {
> +    //
> +    // support for PCI Express feature - Max. Payload Size
> +    //
> +    FALSE,
> +    //
> +    // support for PCI Express feature - Max. Read Request Size
> +    //
> +    FALSE,
> +    //
> +    // support for PCI Express feature - Extended Tag
> +    //
> +    FALSE,
> +    //
> +    // support for PCI Express feature - Relax Order
> +    //
> +    FALSE,
> +    //
> +    // support for PCI Express feature - No-Snoop
> +    //
> +    FALSE,
> +    //
> +    // support for PCI Express feature - ASPM state
> +    //
> +    FALSE,
> +    //
> +    // support for PCI Express feature - Common Clock Configuration
> +    //
> +    FALSE,
> +    //
> +    // support for PCI Express feature - Extended Sync
> +    //
> +    FALSE,
> +    //
> +    // support for PCI Express feature - Atomic Op
> +    //
> +    FALSE,
> +    //
> +    // support for PCI Express feature - LTR
> +    //
> +    FALSE,
> +    //
> +    // support for PCI Express feature - PTM
> +    //
> +    FALSE,
> +    //
> +    // support for PCI Express feature - Completion Timeout
> +    //
> +    FALSE,
> +    //
> +    // support for PCI Express feature - Clock Power Management
> +    //
> +    FALSE,
> +    //
> +    // support for PCI Express feature - L1 PM Substates
> +    //
> +    FALSE
> +};
> +
> +//
> +// indicates the driver has completed query to platform on the list of supported
> +// PCI features to be configured
> +//
> +BOOLEAN   mPciExpressGetPlatformPolicyComplete = FALSE;
> +
> +//
> +// PCI Express feature initialization phase handle routines
> +//
> +PCI_EXPRESS_FEATURE_INITIALIZATION_POINT
> mPciExpressFeatureInitializationList[] = {
> +    //
> +    // vacant entry, shall be replaced with actual entry when the PCI Express
> +    // feature are added.
> +    //
> +  { 0, 0, NULL}
> +};
> +
> +/**
> +  Routine to serially dispatch the designated the PCI Express feature specific
> +  functions defined for each of the configuration phase. The order for each
> phase
> +  would be based entirely on the table mPciExpressFeatureInitializationList.
> +
> +  @param  PciDevice                       pointer to PCI_IO_DEVICE to identify device
> +  @param  PciExFeatureConfigPhase         input configuration phase
> +  @param  PciExpressFeatureConfiguration  used pointer to void to
> accomodate any PCI
> +                                          Express feature specific data type
> +  @retval EFI_STATUS                      output only from feature specific function
> +                                          defined in the table mPciExpressFeatureInitializationList
> +**/
> +EFI_STATUS
> +DispatchPciExpressInitializationFunctions (
> +  IN PCI_IO_DEVICE                            *PciDevice,
> +  IN PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE
> PciExFeatureConfigPhase,
> +  IN VOID                                     *PciExpressFeatureConfiguration
> +  )
> +{
> +  UINTN       idx;
> +  EFI_STATUS  Status;
> +  UINT8       *PciExpressPolicy;
> +
> +  for (
> +      idx = 0, PciExpressPolicy = (UINT8*)&mPciExpressPlatformPolicy
> +      ; idx < sizeof (mPciExpressFeatureInitializationList) / sizeof
> (PCI_EXPRESS_FEATURE_INITIALIZATION_POINT)
> +      ; idx++
> +      ){
> +    if (
> +        //
> +        // match the configuration phase
> +        //
> +
> mPciExpressFeatureInitializationList[idx].PciExpressFeatureConfigurationPhase
> == PciExFeatureConfigPhase
> +        //
> +        // check whether the PCI Express features is enabled
> +        //
> +        &&
> PciExpressPolicy[mPciExpressFeatureInitializationList[idx].PciExpressFeatureId]
> == TRUE
> +        ) {
> +      Status =
> mPciExpressFeatureInitializationList[idx].PciExpressFeatureConfigurationRoutin
> e (
> +                                                            PciDevice,
> +                                                            PciExpressFeatureConfiguration
> +                                                            );
> +    }
> +  }
> +  return Status;
> +}
> +
> +/**
> +  Main routine to indicate platform selection of any of the other PCI features
> +  to be configured by this driver
> +
> +  @retval TRUE    platform has selected the other PCI features to be configured
> +          FALSE   platform has not selected any of the other PCI features
> +**/
> +BOOLEAN
> +CheckPciExpressFeatureList (
> +  )
> +{
> +  UINTN     length;
> +  UINT8     *list;
> +
> +  for (
> +      length = 0, list = (UINT8*)&mPciExpressPlatformPolicy
> +      ; length < sizeof (EFI_PCI_EXPRESS_PLATFORM_POLICY)
> +      ; length++
> +      ) {
> +    if (list[length]) {
> +      return TRUE;
> +    }
> +  }
> +  return FALSE;
> +}
> +
> +/**
> +  helper routine to wipe out the global PCI Express feature list
> +**/
> +VOID
> +NegatePciExpressFeatureList (
> +  )
> +{
> +  UINTN     length;
> +  UINT8      *list;
> +
> +  for (
> +      length = 0, list = (UINT8*)&mPciExpressPlatformPolicy
> +      ; length < sizeof (EFI_PCI_EXPRESS_PLATFORM_POLICY)
> +      ; length++
> +      ) {
> +    if (list[length]) {
> +      list[length] = FALSE;
> +    }
> +  }
> +}
> +
> +/**
> +  Main routine to indicate whether the PCI Express feature initialization is
> +  required or not
> +
> +  @retval TRUE    PCI Express feature initialization required
> +          FALSE   PCI Express feature not required
> +**/
> +BOOLEAN
> +IsPciExpressFeatureConfigurationRequired (
> +  )
> +{
> +  EFI_STATUS    Status;
> +
> +  if (mPciExpressGetPlatformPolicyComplete) {
> +    return CheckPciExpressFeatureList ();
> +  }
> +  //
> +  // initialize the PCI Express feature data members
> +  //
> +  InitializeListHead (&mRootBridgeDeviceList);
> +  //
> +  // check the platform to configure the PCI Express features
> +  //
> +  mPciExpressGetPlatformPolicyComplete = TRUE;
> +
> +  Status = PciExpressPlatformGetPolicy ();
> +  if (EFI_ERROR (Status)) {
> +    //
> +    // fail to obtain the PCI Express feature configuration from platform,
> +    // negate the list to avoid any unwanted configuration
> +    //
> +    NegatePciExpressFeatureList ();
> +    return FALSE;
> +  }
> +  //
> +  // PCI Express feature configuration list is ready from platform
> +  //
> +  return TRUE;
> +}
> +
> +
> +/**
> +  Indicates whether the set of PCI Express features selected by platform
> requires
> +  extended setup, that has additional resources that would be allocated to align
> +  all the devices in the PCI tree, and free the resources later.
> +
> +  @retval TRUE    PCI Express feature requires extended setup
> +          FALSE   PCI Express feature does not require extended setup
> +**/
> +BOOLEAN
> +IsPciExpressFeatureExtendedSetupRequired (
> +  )
> +{
> +  UINTN   idx;
> +  UINT8   *PciExpressPolicy;
> +  //
> +  // return TRUE only for those features which are required to be aligned with
> +  // common values among all the devices in the PCI tree
> +  //
> +  for (
> +      idx = 0, PciExpressPolicy = (UINT8*)&mPciExpressPlatformPolicy
> +      ; idx < sizeof (mPciExpressFeatureInitializationList) / sizeof
> (PCI_EXPRESS_FEATURE_INITIALIZATION_POINT)
> +      ; idx++
> +  ){
> +    if (
> +        //
> +        // match the configuration phase to extended setup phase
> +        //
> +
> mPciExpressFeatureInitializationList[idx].PciExpressFeatureConfigurationPhase
> == PciExpressFeatureEntendedSetupPhase
> +        //
> +        // check whether the PCI Express features is enabled
> +        //
> +        &&
> PciExpressPolicy[mPciExpressFeatureInitializationList[idx].PciExpressFeatureId]
> == TRUE
> +    ) {
> +      return TRUE;
> +    }
> +  }
> +
> +  return FALSE;
> +}
> +
> +/**
> + Helper routine to determine the existence of previously enumerated PCI device
> +
> + @retval  TRUE  PCI device exist
> +          FALSE does not exist
> +**/
> +BOOLEAN
> +DeviceExist (
> +  PCI_IO_DEVICE                   *PciDevice
> +  )
> +{
> +  EFI_PCI_IO_PROTOCOL   *PciIoProtocol = &PciDevice->PciIo;
> +  UINT16                VendorId = 0xFFFF;
> +
> +  PciIoProtocol->Pci.Read (
> +                      PciIoProtocol,
> +                      EfiPciIoWidthUint16,
> +                      PCI_VENDOR_ID_OFFSET,
> +                      1,
> +                      &VendorId
> +                      );
> +  if (VendorId == 0 || VendorId == 0xFFFF) {
> +    return FALSE;
> +  } else {
> +    return TRUE;
> +  }
> +}
> +
> +/**
> +  Free up memory alloted for the primary physical PCI Root ports of the PCI
> Root
> +  Bridge instance. Free up all the nodes of type BRIDGE_DEVICE_NODE.
> +**/
> +VOID
> +DestroyRootBridgeDeviceNodes ()
> +{
> +  LIST_ENTRY                *Link;
> +  BRIDGE_DEVICE_NODE        *Temp;
> +
> +  Link = mRootBridgeDeviceList.ForwardLink;
> +  while (Link != NULL && Link != &mRootBridgeDeviceList) {
> +    Temp = ROOT_BRIDGE_DEVICE_NODE_FROM_LINK (Link);
> +    Link = RemoveEntryList (Link);
> +    FreePool (Temp->PciExFeaturesConfigurationTable);
> +    FreePool (Temp);
> +  }
> +}
> +
> +/**
> +  Main routine to determine the child PCI devices of a PCI bridge device
> +  and group them under a common internal PCI features Configuration table.
> +
> +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> +  @param  PciFeaturesConfigTable          A pointer to a pointer to the
> +                                          PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE.
> +                                          Returns NULL in case of RCiEP or the PCI
> +                                          device does match with any of the physical
> +                                          Root ports, or it does not belong to any
> +                                          Root port's PCI bus range (not a child)
> +
> +  @retval EFI_SUCCESS                     able to determine the PCI feature
> +                                          configuration table. For RCiEP since
> +                                          since it is not prepared.
> +          EFI_DEVICE_ERROR                the PCI device has invalid EFI device
> +                                          path
> +**/
> +EFI_STATUS
> +GetPciExpressFeaturesConfigurationTable (
> +  IN  PCI_IO_DEVICE                             *PciDevice,
> +  OUT PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> **PciFeaturesConfigTable
> +  )
> +{
> +  LIST_ENTRY                *Link;
> +  BRIDGE_DEVICE_NODE        *Temp;
> +  BOOLEAN                   NodeMatch;
> +  EFI_DEVICE_PATH_PROTOCOL  *RootPortPath;
> +  EFI_DEVICE_PATH_PROTOCOL  *PciDevicePath;
> +
> +  if (IsListEmpty (&mRootBridgeDeviceList)) {
> +    //
> +    // no populated PCI primary root ports to parse and match the PCI features
> +    // configuration table
> +    //
> +    *PciFeaturesConfigTable = NULL;
> +    return EFI_SUCCESS;
> +  }
> +
> +  //
> +  // The PCI features configuration table is not built for RCiEP, return NULL
> +  //
> +  if (PciDevice->PciExpressCapabilityStructure.Capability.Bits.DevicePortType ==
> \
> +      PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT) {
> +    *PciFeaturesConfigTable = NULL;
> +    return EFI_SUCCESS;
> +  }
> +
> +  if (IsDevicePathEnd (PciDevice->DevicePath)){
> +    //
> +    // the given PCI device does not have a valid device path
> +    //
> +    *PciFeaturesConfigTable = NULL;
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +
> +  Link = mRootBridgeDeviceList.ForwardLink;
> +  do {
> +    Temp = ROOT_BRIDGE_DEVICE_NODE_FROM_LINK (Link);
> +    RootPortPath = Temp->RootBridgeDevicePath;
> +    PciDevicePath = PciDevice->DevicePath;
> +    NodeMatch = FALSE;
> +    //
> +    // match the device path from the list of primary Root Ports with the given
> +    // device; the initial nodes matching in sequence indicate that the given PCI
> +    // device belongs to that PCI tree from the root port
> +    //
> +    if (IsDevicePathEnd (RootPortPath)) {
> +      //
> +      // critical error as no device path available in root
> +      //
> +      *PciFeaturesConfigTable = NULL;
> +      return EFI_DEVICE_ERROR;
> +    }
> +
> +    if (EfiCompareDevicePath (RootPortPath, PciDevicePath)) {
> +      //
> +      // the given PCI device is the primary root port itself
> +      //
> +      *PciFeaturesConfigTable = Temp->PciExFeaturesConfigurationTable;
> +      return EFI_SUCCESS;
> +    }
> +    //
> +    // check this PCI device belongs to the primary root port of the root bridge
> +    // any child PCI device will have the same initial device path nodes  as
> +    // its parent root port
> +    //
> +    while (!IsDevicePathEnd (RootPortPath)){
> +
> +      if (DevicePathNodeLength (RootPortPath) != DevicePathNodeLength
> (PciDevicePath)) {
> +        //
> +        // break to check the next primary root port nodes as does not match
> +        //
> +        NodeMatch = FALSE;
> +        break;
> +      }
> +      if (CompareMem (RootPortPath, PciDevicePath, DevicePathNodeLength
> (RootPortPath)) != 0) {
> +        //
> +        // node does not match, break to check next node
> +        //
> +        NodeMatch = FALSE;
> +        break;
> +      }
> +      NodeMatch = TRUE;
> +      //
> +      // advance to next node
> +      //
> +      RootPortPath = NextDevicePathNode (RootPortPath);
> +      PciDevicePath = NextDevicePathNode (PciDevicePath);
> +    }
> +
> +    if (NodeMatch == TRUE) {
> +      //
> +      // device belongs to primary root port, return its PCI feature configuration
> +      // table
> +      //
> +      *PciFeaturesConfigTable = Temp->PciExFeaturesConfigurationTable;
> +      return EFI_SUCCESS;
> +    }
> +
> +    //
> +    // advance to next Root port node
> +    //
> +    Link = Link->ForwardLink;
> +  } while (Link != &mRootBridgeDeviceList && Link != NULL);
> +  //
> +  // the PCI device must be RCiEP, does not belong to any primary root port
> +  //
> +  *PciFeaturesConfigTable = NULL;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  helper routine to dump the PCIe Device Port Type
> +**/
> +VOID
> +DumpDevicePortType (
> +  IN  UINT8   DevicePortType
> +  )
> +{
> +  switch (DevicePortType){
> +    case PCIE_DEVICE_PORT_TYPE_PCIE_ENDPOINT:
> +      DEBUG (( DEBUG_INFO, "PCIe endpoint found\n"));
> +      break;
> +    case PCIE_DEVICE_PORT_TYPE_LEGACY_PCIE_ENDPOINT:
> +      DEBUG (( DEBUG_INFO, "legacy PCI endpoint found\n"));
> +      break;
> +    case PCIE_DEVICE_PORT_TYPE_ROOT_PORT:
> +      DEBUG (( DEBUG_INFO, "PCIe Root Port found\n"));
> +      break;
> +    case PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT:
> +      DEBUG (( DEBUG_INFO, "PCI switch upstream port found\n"));
> +      break;
> +    case PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT:
> +      DEBUG (( DEBUG_INFO, "PCI switch downstream port found\n"));
> +      break;
> +    case PCIE_DEVICE_PORT_TYPE_PCIE_TO_PCI_BRIDGE:
> +      DEBUG (( DEBUG_INFO, "PCIe-PCI bridge found\n"));
> +      break;
> +    case PCIE_DEVICE_PORT_TYPE_PCI_TO_PCIE_BRIDGE:
> +      DEBUG (( DEBUG_INFO, "PCI-PCIe bridge found\n"));
> +      break;
> +    case PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT:
> +      DEBUG (( DEBUG_INFO, "RCiEP found\n"));
> +      break;
> +    case PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_EVENT_COLLECTOR:
> +      DEBUG (( DEBUG_INFO, "RC Event Collector found\n"));
> +      break;
> +  }
> +}
> +
> +/**
> +   Setup each PCI device as per the pltaform's device-specific policy, in
> accordance
> +   with PCI Express Base specification.
> +
> +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> +
> +  @retval EFI_SUCCESS           processing each PCI feature as per policy defined
> +                                was successful.
> + **/
> +EFI_STATUS
> +SetupDevicePciExpressFeatures (
> +  IN  PCI_IO_DEVICE                           *PciDevice,
> +  IN  PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE PciConfigPhase
> +  )
> +{
> +  EFI_STATUS                              Status;
> +  PCI_REG_PCIE_CAPABILITY                 PcieCap;
> +  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> *PciExpressFeaturesConfigTable;
> +
> +  PciExpressFeaturesConfigTable = NULL;
> +  Status = GetPciExpressFeaturesConfigurationTable (PciDevice,
> &PciExpressFeaturesConfigTable);
> +
> +  if (PciConfigPhase == PciExpressFeatureSetupPhase) {
> +    DEBUG_CODE (
> +      if (EFI_ERROR( Status)) {
> +        DEBUG ((
> +          DEBUG_WARN,
> +          "[Cfg group: 0 {error in dev path}]"
> +          ));
> +      } else if (PciExpressFeaturesConfigTable == NULL) {
> +        DEBUG ((
> +          DEBUG_INFO,
> +          "[Cfg group: 0]"
> +          ));
> +      } else {
> +        DEBUG ((
> +          DEBUG_INFO,
> +          "[Cfg group: %d]",
> +          PciExpressFeaturesConfigTable->ID
> +          ));
> +      }
> +      PcieCap.Uint16 = PciDevice-
> >PciExpressCapabilityStructure.Capability.Uint16;
> +      DumpDevicePortType ((UINT8)PcieCap.Bits.DevicePortType);
> +    );
> +
> +    //
> +    // get the device-specific platform policy for the PCI Express features
> +    //
> +    Status = PciExpressPlatformGetDevicePolicy (PciDevice);
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "Error in obtaining PCI device policy!!!\n"
> +        ));
> +    }
> +  }
> +
> +  DEBUG ((DEBUG_INFO, "["));
> +
> +  Status = DispatchPciExpressInitializationFunctions (
> +            PciDevice,
> +            PciConfigPhase,
> +            PciExpressFeaturesConfigTable
> +            );
> +
> +  DEBUG ((DEBUG_INFO, "]\n"));
> +  return Status;
> +}
> +
> +/**
> +  Create and append a node of type BRIDGE_DEVICE_NODE in the list for the
> primary
> +  Root Port so that all its child PCI devices can be identified against the PCI
> +  features configuration table group ID, of type
> PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE.
> +
> +  @param BridgePort    A pointer to the PCI_IO_DEVICE
> +  @param PortNumber    A UINTN value to identify the PCI feature
> configuration
> +                       table group
> +
> +  @retval EFI_SUCCESS           success in adding a node of
> BRIDGE_DEVICE_NODE
> +                                to the list
> +          EFI_OUT_OF_RESOURCES  unable to get memory for creating the node
> +**/
> +EFI_STATUS
> +CreatePciRootBridgeDeviceNode (
> +  IN  PCI_IO_DEVICE           *BridgePort,
> +  IN  UINTN                   PortNumber
> +  )
> +{
> +  BRIDGE_DEVICE_NODE                        *RootBridgeNode = NULL;
> +  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE  *PciConfigTable = NULL;
> +
> +  RootBridgeNode = AllocateZeroPool (sizeof (BRIDGE_DEVICE_NODE));
> +  if (RootBridgeNode == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  RootBridgeNode->Signature                     =
> PCI_ROOT_BRIDGE_DEVICE_SIGNATURE;
> +  RootBridgeNode->RootBridgeDevicePath          = BridgePort->DevicePath;
> +  PciConfigTable = AllocateZeroPool (
> +                     sizeof (PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE)
> +                     );
> +  if (PciConfigTable) {
> +    PciConfigTable->ID                          = PortNumber;
> +  }
> +
> +  RootBridgeNode->PciExFeaturesConfigurationTable  = PciConfigTable;
> +
> +  InsertTailList (&mRootBridgeDeviceList, &RootBridgeNode-
> >NextRootBridgeDevice);
> +
> +  if (PciConfigTable == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Scan all the nodes of the RootBridge to identify and create a separate list
> +  of all primary physical PCI root ports and link each with its own instance of
> +  the PCI Feature Configuration Table.
> +
> +  @param  RootBridge    A pointer to the PCI_IO_DEVICE of the PCI Root Bridge
> +
> +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store PCI
> feature
> +                                configuration table for all the physical PCI root
> +                                ports given
> +          EFI_NOT_FOUND         No PCI Bridge device found
> +          EFI_SUCCESS           PCI Feature COnfiguration table created for all
> +                                the PCI Rooot ports found
> +          EFI_INVALID_PARAMETER invalid parameter passed to the routine which
> +                                creates the PCI controller node for the primary
> +                                Root post list
> +**/
> +EFI_STATUS
> +CreatePciRootBridgeDeviceList (
> +  IN  PCI_IO_DEVICE           *RootBridge
> +  )
> +{
> +  EFI_STATUS              Status = EFI_NOT_FOUND;
> +  LIST_ENTRY              *Link;
> +  PCI_IO_DEVICE           *Device;
> +  UINTN                   BridgeDeviceCount;
> +
> +  BridgeDeviceCount = 0;
> +  for ( Link = RootBridge->ChildList.ForwardLink
> +      ; Link != &RootBridge->ChildList
> +      ; Link = Link->ForwardLink
> +  ) {
> +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> +    if (!DeviceExist (Device)) {
> +      continue;
> +    }
> +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> +      BridgeDeviceCount++;
> +      DEBUG ((
> +        DEBUG_INFO,
> +        "#%d ::Bridge [%02x|%02x|%02x]",
> +        BridgeDeviceCount, Device->BusNumber, Device->DeviceNumber, Device-
> >FunctionNumber
> +        ));
> +      //
> +      // create a list of bridge devices if that is connected to any other device
> +      //
> +      if (!IsListEmpty (&Device->ChildList)) {
> +        DEBUG ((
> +          DEBUG_INFO,
> +          "- has downstream device!\n"
> +          ));
> +        Status = CreatePciRootBridgeDeviceNode (Device, BridgeDeviceCount);
> +        if (EFI_ERROR (Status)) {
> +          DEBUG ((
> +            DEBUG_ERROR,
> +            "PCI configuration table allocation failure for #%d ::Bridge
> [%02x|%02x|%02x]\n",
> +            BridgeDeviceCount, Device->BusNumber, Device->DeviceNumber,
> Device->FunctionNumber
> +            ));
> +        }
> +      } else {
> +        DEBUG ((
> +          DEBUG_INFO,
> +          "- no downstream device!\n"
> +          ));
> +      }
> +    }
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Initialize the device's PCI Express features, in a staged manner
> +  @param  PciDevice             A pointer to the PCI_IO_DEVICE.
> +
> +  @retval EFI_SUCCESS           initializing all the nodes of the root bridge
> +                                instances were successfull.
> +**/
> +EFI_STATUS
> +InitializeDevicePciExpressFeatures (
> +  IN  PCI_IO_DEVICE                           *PciDevice,
> +  IN  PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE PciConfigPhase
> +  )
> +{
> +  EFI_STATUS            Status;
> +
> +  switch (PciConfigPhase) {
> +    case PciExpressFeatureSetupPhase:
> +    case PciExpressFeatureEntendedSetupPhase:
> +    case PciExpressFeatureProgramPhase:
> +      Status = SetupDevicePciExpressFeatures (PciDevice, PciConfigPhase);
> +      break;
> +    case PciExpressFeatureEndPhase:
> +      Status = PciExpressPlatformNotifyDeviceState (PciDevice);
> +      break;
> +  }
> +  return Status;
> +}
> +
> +/**
> +  Traverse all the nodes from the root bridge or PCI-PCI bridge instance, to
> +  configure the PCI Express features as per the PCI Express Base Secification
> +  by considering its device-specific platform policy, and its device capability,
> +  as applicable.
> +
> +  @param RootBridge             A pointer to the PCI_IO_DEVICE.
> +
> +  @retval EFI_SUCCESS           Traversing all the nodes of the root bridge
> +                                instances were successfull.
> +**/
> +EFI_STATUS
> +InitializePciExpressFeatures (
> +  IN  PCI_IO_DEVICE                           *RootBridge,
> +  IN  PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE PciConfigPhase
> +  )
> +{
> +  EFI_STATUS            Status;
> +  LIST_ENTRY            *Link;
> +  PCI_IO_DEVICE         *Device;
> +
> +  for ( Link = RootBridge->ChildList.ForwardLink
> +      ; Link != &RootBridge->ChildList
> +      ; Link = Link->ForwardLink
> +  ) {
> +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> +    if (!DeviceExist (Device)) {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "::Device [%02x|%02x|%02x] - does not exist!!!\n",
> +        Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
> +        ));
> +      continue;
> +    }
> +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> +      DEBUG ((
> +        DEBUG_INFO,
> +        "::Bridge [%02x|%02x|%02x] -",
> +        Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
> +        ));
> +      if (Device->IsPciExp) {
> +        Status = InitializeDevicePciExpressFeatures (
> +                  Device,
> +                  PciConfigPhase
> +                  );
> +      } else {
> +        DEBUG ((
> +          DEBUG_INFO,
> +          "Not a PCIe capable device!\n"
> +          ));
> +        //
> +        // PCI Bridge which does not have PCI Express Capability structure
> +        // cannot process this kind of PCI Bridge device
> +        //
> +      }
> +
> +      InitializePciExpressFeatures (Device, PciConfigPhase);
> +    } else {
> +      DEBUG ((
> +        DEBUG_INFO,
> +        "::Device [%02x|%02x|%02x] -",
> +        Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
> +        ));
> +      if (Device->IsPciExp) {
> +        Status = InitializeDevicePciExpressFeatures (
> +                  Device,
> +                  PciConfigPhase
> +                  );
> +      } else {
> +        DEBUG ((
> +          DEBUG_INFO,
> +          "Not a PCIe capable device!\n"
> +          ));
> +        //
> +        // PCI Device which does not have PCI Express Capability structure
> +        // cannot process this kind of PCI device
> +        //
> +      }
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Enumerate all the nodes of the specified root bridge or PCI-PCI Bridge, to
> +  configure the other PCI features.
> +
> +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> +
> +  @retval EFI_SUCCESS           The other PCI features configuration during
> enumeration
> +                                of all the nodes of the PCI root bridge instance were
> +                                programmed in PCI-compliance pattern along with the
> +                                device-specific policy, as applicable.
> +  @retval EFI_UNSUPPORTED       One of the override operation maong the
> nodes of
> +                                the PCI hierarchy resulted in a incompatible address
> +                                range.
> +  @retval EFI_INVALID_PARAMETER The override operation is performed with
> invalid input
> +                                parameters.
> +**/
> +EFI_STATUS
> +EnumeratePciExpressFeatures (
> +  IN EFI_HANDLE             Controller,
> +  IN PCI_IO_DEVICE          *RootBridge
> +  )
> +{
> +  EFI_STATUS            Status;
> +  UINTN                 PciExpressFeatureConfigPhase;
> +
> +  if (!IsPciExpressFeatureConfigurationRequired ()) {
> +    //
> +    // exit as agreement is not reached with platform to configure the PCI
> +    // Express features
> +    //
> +    return EFI_SUCCESS;
> +  }
> +  mRootBridgeHandle = Controller;
> +
> +  DEBUG_CODE (
> +    CHAR16                *Str;
> +    Str = ConvertDevicePathToText (
> +            DevicePathFromHandle (RootBridge->Handle),
> +            FALSE,
> +            FALSE
> +            );
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "Enumerating PCI features for Root Bridge %s\n",
> +      Str != NULL ? Str : L""
> +      ));
> +
> +    if (Str != NULL) {
> +      FreePool (Str);
> +    }
> +  );
> +
> +  for ( PciExpressFeatureConfigPhase = PciExpressFeaturePreProcessPhase
> +      ; PciExpressFeatureConfigPhase <= PciExpressFeatureEndPhase
> +      ; PciExpressFeatureConfigPhase++
> +      ) {
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "<<********** Phase [%d]**********>>\n",
> +      PciExpressFeatureConfigPhase
> +      ));
> +    if (PciExpressFeatureConfigPhase == PciExpressFeaturePreProcessPhase) {
> +      //
> +      // create a list of root bridge devices (root ports) of the root complex
> +      // if extra setup phase required
> +      //
> +      if (IsPciExpressFeatureExtendedSetupRequired ()) {
> +        CreatePciRootBridgeDeviceList (RootBridge);
> +      }
> +      continue;
> +    }
> +    if (PciExpressFeatureConfigPhase == PciExpressFeatureEntendedSetupPhase)
> {
> +      if (!IsPciExpressFeatureExtendedSetupRequired ()) {
> +        //
> +        // since the PCI Express features require no extra initialization steps
> +        // skip this phase
> +        //
> +        continue;
> +      }
> +    }
> +    //
> +    // setup the PCI Express features
> +    //
> +    Status = InitializePciExpressFeatures (RootBridge,
> PciExpressFeatureConfigPhase);
> +
> +    if (PciExpressFeatureConfigPhase == PciExpressFeatureEndPhase) {
> +      //
> +      // clean up the temporary resource nodes created for this root bridge
> +      //
> +      if (IsPciExpressFeatureExtendedSetupRequired ()) {
> +        DestroyRootBridgeDeviceNodes ();
> +      }
> +    }
> +  }
> +
> +  return Status;
> +}
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> new file mode 100644
> index 0000000..2eff8aa
> --- /dev/null
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> @@ -0,0 +1,226 @@
> +/** @file
> +  PCI standard feature support functions implementation for PCI Bus module..
> +
> +Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef _EFI_PCI_FEATURES_SUPPORT_H_
> +#define _EFI_PCI_FEATURES_SUPPORT_H_
> +
> +extern  EFI_HANDLE                                  mRootBridgeHandle;
> +extern  EFI_PCI_EXPRESS_PLATFORM_POLICY
> mPciExpressPlatformPolicy;
> +//
> +// defines the data structure to hold the details of the PCI Root port devices
> +//
> +typedef struct _BRIDGE_DEVICE_NODE  BRIDGE_DEVICE_NODE;
> +
> +//
> +// defines the data structure to hold the configuration data for the other PCI
> +// features
> +//
> +typedef struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE;
> +
> +//
> +// define the data type for the PCI feature policy support
> +//
> +typedef struct _PCI_FEATURE_POLICY  PCI_FEATURE_POLICY;
> +
> +//
> +// Signature value for the PCI Root Port node
> +//
> +#define PCI_ROOT_BRIDGE_DEVICE_SIGNATURE               SIGNATURE_32 ('p',
> 'c', 'i', 'p')
> +
> +//
> +// Definitions of the PCI Root Port data structure members
> +//
> +struct _BRIDGE_DEVICE_NODE {
> +  //
> +  // Signature header
> +  //
> +  UINT32                                    Signature;
> +  //
> +  // linked list pointers to next node
> +  //
> +  LIST_ENTRY                                NextRootBridgeDevice;
> +  //
> +  // pointer to PCI_IO_DEVICE of the primary PCI Controller device
> +  //
> +  EFI_DEVICE_PATH_PROTOCOL                  *RootBridgeDevicePath;
> +  //
> +  // pointer to the corresponding PCI Express feature configuration Table node
> +  // all the child PCI devices of the controller are aligned based on this table
> +  //
> +  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> *PciExFeaturesConfigurationTable;
> +};
> +
> +#define ROOT_BRIDGE_DEVICE_NODE_FROM_LINK(a) \
> +  CR (a, BRIDGE_DEVICE_NODE, NextRootBridgeDevice,
> PCI_ROOT_BRIDGE_DEVICE_SIGNATURE)
> +
> +//
> +// Definition of the PCI Feature configuration Table members
> +//
> +struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE {
> +  //
> +  // Configuration Table ID
> +  //
> +  UINTN                                     ID;
> +};
> +
> +//
> +// Declaration of the internal sub-phases during enumeration to configure the
> PCI
> +// Express features
> +//
> +typedef enum {
> +  //
> +  // preprocessing applicable only to few PCI Express features to bind all devices
> +  // under the common root bridge device (root port), that would be useful to
> align
> +  // all devices with a common value. This would be optional phase based on
> the
> +  // type of the PCI Express feature to be programmed based on platform policy
> +  //
> +  PciExpressFeaturePreProcessPhase,
> +
> +  //
> +  // mandatory phase to setup the PCI Express feature to its applicable
> attribute,
> +  // based on its device-specific platform policies, matching with its device
> capabilities
> +  //
> +  PciExpressFeatureSetupPhase,
> +
> +  //
> +  // optional phase primarily to align all devices, specially required when PCI
> +  // switch is present in the hierarchy, applicable to certain few PCI Express
> +  // features only
> +  //
> +  PciExpressFeatureEntendedSetupPhase,
> +
> +  //
> +  // mandatory programming phase to complete the configuration of the PCI
> Express
> +  // features
> +  //
> +  PciExpressFeatureProgramPhase,
> +
> +  //
> +  // optional phase to clean up temporary buffers, like those that were
> prepared
> +  // during the preprocessing phase above
> +  //
> +  PciExpressFeatureEndPhase
> +
> +}PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE;
> +
> +//
> +// declaration for the data type to harbor the PCI feature policies
> +//
> +struct  _PCI_FEATURE_POLICY {
> +  //
> +  // if set, it indicates the feature should be enabled
> +  // if clear, it indicates the feature should be disabled
> +  //
> +  UINT8   Act : 1;
> +  //
> +  // this field will be specific to feature, it can be implementation specific
> +  // or it can be reserved and remain unused
> +  //
> +  UINT8   Support : 6;
> +  //
> +  // if set indicates override the feature policy defined by the members above
> +  // if clear it indicates that this feature policy should be ignored completely
> +  // this means the above two members should not be used
> +  //
> +  UINT8   Override : 1;
> +};
> +
> +//
> +// Declaration of the PCI Express features unique Id
> +//
> +typedef enum {
> +  //
> +  // support for PCI Express feature - Max. Payload Size
> +  //
> +  PciExpressMps,
> +  //
> +  // support for PCI Express feature - Max. Read Request Size
> +  //
> +  PciExpressMrrs,
> +  //
> +  // support for PCI Express feature - Extended Tag
> +  //
> +  PciExpressExtTag,
> +  //
> +  // support for PCI Express feature - Relax Order
> +  //
> +  PciExpressRelaxOrder,
> +  //
> +  // support for PCI Express feature - No-Snoop
> +  //
> +  PciExpressNoSnoop,
> +  //
> +  // support for PCI Express feature - ASPM state
> +  //
> +  PciExpressAspm,
> +  //
> +  // support for PCI Express feature - Common Clock Configuration
> +  //
> +  PciExpressCcc,
> +  //
> +  // support for PCI Express feature - Extended Sync
> +  //
> +  PciExpressExtSync,
> +  //
> +  // support for PCI Express feature - Atomic Op
> +  //
> +  PciExpressAtomicOp,
> +  //
> +  // support for PCI Express feature - LTR
> +  //
> +  PciExpressLtr,
> +  //
> +  // support for PCI Express feature - PTM
> +  //
> +  PciExpressPtm,
> +  //
> +  // support for PCI Express feature - Completion Timeout
> +  //
> +  PciExpressCto,
> +  //
> +  // support for PCI Express feature - Clock Power Management
> +  //
> +  PciExpressCpm,
> +  //
> +  // support for PCI Express feature - L1 PM Substates
> +  //
> +  PciExpressL1PmSubstates
> +
> +} PCI_EXPRESS_FEATURE_ID;
> +
> +//
> +// PCI Express feature configuration routine during initialization phases
> +//
> +typedef
> +EFI_STATUS
> +(*PCI_EXPRESS_FEATURE_CONFIGURATION_ROUTINE) (
> +  IN PCI_IO_DEVICE                            *PciDevice,
> +  IN VOID                                     *PciExpressFeatureConfiguration
> +  );
> +
> +//
> +// data type for the PCI Express feature initialization phases
> +//
> +typedef struct {
> +  //
> +  // Pci Express feature configuration phase
> +  //
> +  PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE
> PciExpressFeatureConfigurationPhase;
> +  //
> +  // PCI Express feature Id
> +  //
> +  PCI_EXPRESS_FEATURE_ID                    PciExpressFeatureId;
> +  //
> +  // PCI Express feature configuration routine
> +  //
> +  PCI_EXPRESS_FEATURE_CONFIGURATION_ROUTINE
> PciExpressFeatureConfigurationRoutine;
> +
> +}PCI_EXPRESS_FEATURE_INITIALIZATION_POINT;
> +
> +
> +#endif
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> new file mode 100644
> index 0000000..31c675d
> --- /dev/null
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> @@ -0,0 +1,302 @@
> +/** @file
> +  This file encapsulate the usage of PCI Platform Protocol
> +
> +  This file define the necessary hooks used to obtain the platform
> +  level data and policies which could be used in the PCI Enumeration phases
> +
> +Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "PciBus.h"
> +
> +
> +EFI_PCI_EXPRESS_PLATFORM_PROTOCOL             *mPciExPlatformProtocol;
> +EFI_PCI_EXPRESS_OVERRIDE_PROTOCOL             *mPciExOverrideProtocol;
> +
> +
> +/**
> +  This function retrieves the PCI Express Platform Protocols published by
> platform
> +  @retval EFI_STATUS          direct return status from the LocateProtocol ()
> +                              boot service for the PCI Express Override Protocol
> +          EFI_SUCCESS         The PCI Express Platform Protocol is found
> +**/
> +EFI_STATUS
> +GetPciExpressProtocol (
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  if (mPciExPlatformProtocol) {
> +    //
> +    // the PCI Express Platform Protocol is already initialized
> +    //
> +    return EFI_SUCCESS;
> +  }
> +  if (mPciExOverrideProtocol) {
> +    //
> +    // the PCI Express Override Protocol is already initialized
> +    //
> +    return EFI_SUCCESS;
> +  }
> +  //
> +  // locate the PCI Express Platform Protocol
> +  //
> +  Status = gBS->LocateProtocol (
> +                  &gEfiPciExpressPlatformProtocolGuid,
> +                  NULL,
> +                  (VOID **) &mPciExPlatformProtocol
> +                  );
> +  if (!EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +  //
> +  // If PCI Express Platform protocol doesn't exist, try to get the Pci Express
> +  // Override Protocol.
> +  //
> +  return gBS->LocateProtocol (
> +                &gEfiPciExpressOverrideProtocolGuid,
> +                NULL,
> +                (VOID **) &mPciExOverrideProtocol
> +                );
> +}
> +
> +/**
> +  This function indicates that the platform has published the PCI Express
> Platform
> +  Protocol (or PCI Express Override Protocol) to indicate that this driver can
> +  initialize the PCI Express features.
> +  @retval     TRUE or FALSE
> +**/
> +BOOLEAN
> +IsPciExpressProtocolPresent (
> +  )
> +{
> +  if (
> +      mPciExPlatformProtocol == NULL
> +      && mPciExOverrideProtocol == NULL
> +      ) {
> +    return FALSE;
> +  }
> +  return TRUE;
> +}
> +
> +
> +/**
> +  Generic routine to setup the PCI features as per its predetermined defaults.
> +**/
> +VOID
> +SetupDefaultPciExpressDevicePolicy (
> +  IN  PCI_IO_DEVICE               *PciDevice
> +  )
> +{
> +
> +}
> +
> +/**
> +  initialize the device policy data members
> +**/
> +VOID
> +InitializeDevicePolicyData (
> +  IN EFI_PCI_EXPRESS_DEVICE_POLICY  *PciExpressDevicePolicy
> +  )
> +{
> +  UINTN     length;
> +  UINT8     *PciExpressPolicy;
> +  UINT8     *PciExDevicePolicy;
> +
> +
> +  ZeroMem (PciExpressDevicePolicy, sizeof
> (EFI_PCI_EXPRESS_DEVICE_POLICY));
> +
> +  for (
> +      length = 0
> +      , PciExpressPolicy = (UINT8*)&mPciExpressPlatformPolicy
> +      , PciExDevicePolicy = (UINT8*)PciExpressDevicePolicy
> +      ; length < sizeof (EFI_PCI_EXPRESS_PLATFORM_POLICY)
> +      ; length++
> +      ) {
> +    if (!PciExpressPolicy[length]) {
> +      PciExDevicePolicy[length] = EFI_PCI_EXPRESS_NOT_APPLICABLE;
> +    }
> +  }
> +}
> +
> +/**
> +  Intermediate routine to either get the PCI device specific platform policies
> +  through the PCI Platform Protocol, or its alias the PCI Override Protocol.
> +
> +  @param  PciDevice           A pointer to PCI_IO_DEVICE
> +  @param  PciPlatformProtocol A pointer to
> EFI_PCI_EXPRESS_PLATFORM_PROTOCOL
> +
> +  @retval EFI_STATUS          The direct status from the PCI Platform Protocol
> +  @retval EFI_SUCCESS         if on returning predetermined PCI features defaults,
> +                              for the case when protocol returns as EFI_UNSUPPORTED
> +                              to indicate PCI device exist and it has no platform
> +                              policy defined.
> +**/
> +EFI_STATUS
> +GetPciExpressDevicePolicy (
> +  IN  PCI_IO_DEVICE                     *PciDevice,
> +  IN  EFI_PCI_EXPRESS_PLATFORM_PROTOCOL *PciPlatformProtocol
> +  )
> +{
> +  EFI_PCI_EXPRESS_DEVICE_POLICY               PciExpressDevicePolicy;
> +  EFI_STATUS                                  Status;
> +  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress;
> +
> +  PciAddress.Bus = PciDevice->BusNumber;
> +  PciAddress.Device = PciDevice->DeviceNumber;
> +  PciAddress.Function = PciDevice->FunctionNumber;
> +  PciAddress.Register = 0;
> +  PciAddress.ExtendedRegister = 0;
> +
> +  InitializeDevicePolicyData (&PciExpressDevicePolicy);
> +  Status = PciPlatformProtocol->GetDevicePolicy (
> +                                  PciPlatformProtocol,
> +                                  mRootBridgeHandle,
> +                                  PciAddress,
> +                                  sizeof (EFI_PCI_EXPRESS_DEVICE_POLICY),
> +                                  &PciExpressDevicePolicy
> +                                  );
> +  if (!EFI_ERROR(Status)) {
> +    //
> +    // platform chipset policies are returned for this PCI device
> +    //
> +
> +
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "[device policy: platform]"
> +      ));
> +    return Status;
> +  } else if (Status == EFI_UNSUPPORTED) {
> +    //
> +    // platform chipset policies are not provided for this PCI device
> +    // let the enumeration happen as per the PCI standard way
> +    //
> +    SetupDefaultPciExpressDevicePolicy (PciDevice);
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "[device policy: default]"
> +      ));
> +    return EFI_SUCCESS;
> +  }
> +  DEBUG ((
> +    DEBUG_ERROR,
> +    "[device policy: none (error)]"
> +    ));
> +  return Status;
> +}
> +
> +/**
> +  Gets the PCI device-specific platform policy from the PCI Express Platform
> Protocol.
> +  If no PCI Platform protocol is published than setup the PCI feature to
> predetermined
> +  defaults, in order to align all the PCI devices in the PCI hierarchy, as
> applicable.
> +
> +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> +
> +  @retval EFI_STATUS    The direct status from the PCI Platform Protocol
> +  @retval EFI_SUCCESS   On return of predetermined PCI features defaults, for
> +                        the case when protocol returns as EFI_UNSUPPORTED to
> +                        indicate PCI device exist and it has no platform policy
> +                        defined. Also, on returns when no PCI Platform Protocol
> +                        exist.
> +**/
> +EFI_STATUS
> +PciExpressPlatformGetDevicePolicy (
> +  IN PCI_IO_DEVICE          *PciDevice
> +  )
> +{
> +  if (mPciExPlatformProtocol != NULL) {
> +    return GetPciExpressDevicePolicy (PciDevice, mPciExPlatformProtocol);
> +  } else if (mPciExOverrideProtocol != NULL) {
> +    return GetPciExpressDevicePolicy (PciDevice, mPciExOverrideProtocol);
> +  } else {
> +    //
> +    // no protocol found, platform does not require the PCI Express initialization
> +    //
> +    return EFI_UNSUPPORTED;
> +  }
> +}
> +
> +/**
> +  This function gets the platform requirement to initialize the list of PCI Express
> +  features from the protocol definition supported.
> +  This function should be called after the LocatePciPlatformProtocol.
> +  @retval EFI_SUCCESS           return by platform to acknowledge the list of
> +                                PCI Express feature to be configured
> +                                (in mPciExpressPlatformPolicy)
> +          EFI_INVALID_PARAMETER platform does not support the protocol
> arguements
> +                                passed
> +          EFI_UNSUPPORTED       platform did not published the protocol
> +**/
> +EFI_STATUS
> +PciExpressPlatformGetPolicy (
> +  )
> +{
> +  EFI_STATUS    Status;
> +
> +  if (mPciExPlatformProtocol) {
> +    Status = mPciExPlatformProtocol->GetPolicy (
> +                                      mPciExPlatformProtocol,
> +                                      sizeof (EFI_PCI_EXPRESS_PLATFORM_POLICY),
> +                                      &mPciExpressPlatformPolicy
> +                                      );
> +  } else if (mPciExOverrideProtocol) {
> +    Status = mPciExOverrideProtocol->GetPolicy (
> +                                      mPciExOverrideProtocol,
> +                                      sizeof (EFI_PCI_EXPRESS_PLATFORM_POLICY),
> +                                      &mPciExpressPlatformPolicy
> +                                      );
> +  } else {
> +    //
> +    // no protocol found, platform does not require the PCI Express initialization
> +    //
> +    return EFI_UNSUPPORTED;
> +  }
> +  return Status;
> +}
> +
> +
> +/**
> +  Notifies the platform about the current PCI Express state of the device.
> +
> +  @param  PciDevice                 A pointer to PCI_IO_DEVICE
> +  @param  PciExDeviceConfiguration  Pointer to
> EFI_PCI_EXPRESS_DEVICE_CONFIGURATION.
> +                                    Used to pass the current state of device to
> +                                    platform.
> +
> +  @retval EFI_STATUS        The direct status from the PCI Express Platform
> Protocol
> +  @retval EFI_UNSUPPORTED   returns when the PCI Express Platform Protocol
> or its
> +                            alias PCI Express OVerride Protocol is not present.
> +**/
> +EFI_STATUS
> +PciExpressPlatformNotifyDeviceState (
> +  IN PCI_IO_DEVICE                        *PciDevice
> +  )
> +{
> +  EFI_PCI_EXPRESS_DEVICE_CONFIGURATION      PciExDeviceConfiguration;
> +
> +
> +  if (mPciExPlatformProtocol != NULL) {
> +    return mPciExPlatformProtocol->NotifyDeviceState (
> +                                    mPciExPlatformProtocol,
> +                                    PciDevice->Handle,
> +                                    sizeof (EFI_PCI_EXPRESS_DEVICE_CONFIGURATION),
> +                                    &PciExDeviceConfiguration
> +                                    );
> +  } else if (mPciExOverrideProtocol != NULL) {
> +    return mPciExOverrideProtocol->NotifyDeviceState (
> +                                    mPciExOverrideProtocol,
> +                                    PciDevice->Handle,
> +                                    sizeof (EFI_PCI_EXPRESS_DEVICE_CONFIGURATION),
> +                                    &PciExDeviceConfiguration
> +                                    );
> +  } else {
> +    //
> +    // unexpected error
> +    //
> +    return EFI_UNSUPPORTED;
> +  }
> +}
> +
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> new file mode 100644
> index 0000000..4283b81
> --- /dev/null
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> @@ -0,0 +1,87 @@
> +/** @file
> +  This file encapsulate the usage of PCI Platform Protocol
> +
> +  This file define the necessary hooks used to obtain the platform
> +  level data and policies which could be used in the PCI Enumeration phases
> +
> +Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +
> +#ifndef _EFI_PCI_PLATFORM_SUPPORT_H_
> +#define _EFI_PCI_PLATFORM_SUPPORT_H_
> +
> +
> +/**
> +  This function retrieves the PCI Express Platform Protocols published by
> platform
> +  @retval EFI_STATUS          direct return status from the LocateProtocol ()
> +                              boot service for the PCI Express Override Protocol
> +          EFI_SUCCESS         The PCI Express Platform Protocol is found
> +**/
> +EFI_STATUS
> +GetPciExpressProtocol (
> +  );
> +
> +/**
> +  This function indicates that the platform has published the PCI Express
> Platform
> +  Protocol (or PCI Express Override Protocol) to indicate that this driver can
> +  initialize the PCI Express features.
> +  @retval     TRUE or FALSE
> +**/
> +BOOLEAN
> +IsPciExpressProtocolPresent (
> +  );
> +
> +/**
> +  This function gets the platform requirement to initialize the list of PCI Express
> +  features from the protocol definition supported.
> +  This function should be called after the LocatePciPlatformProtocol.
> +  @retval EFI_SUCCESS           return by platform to acknowledge the list of
> +                                PCI Express feature to be configured
> +                                (in mPciExpressPlatformPolicy)
> +          EFI_INVALID_PARAMETER platform does not support the protocol
> arguements
> +                                passed
> +          EFI_UNSUPPORTED       platform did not published the protocol
> +**/
> +EFI_STATUS
> +PciExpressPlatformGetPolicy (
> +  );
> +
> +/**
> +  Gets the PCI device-specific platform policy from the PCI Platform Protocol.
> +  If no PCI Platform protocol is published than setup the PCI feature to
> predetermined
> +  defaults, in order to align all the PCI devices in the PCI hierarchy, as
> applicable.
> +
> +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> +
> +  @retval EFI_STATUS    The direct status from the PCI Platform Protocol
> +  @retval EFI_SUCCESS   On return of predetermined PCI features defaults, for
> +                        the case when protocol returns as EFI_UNSUPPORTED to
> +                        indicate PCI device exist and it has no platform policy
> +                        defined. Also, on returns when no PCI Platform Protocol
> +                        exist.
> +**/
> +EFI_STATUS
> +PciExpressPlatformGetDevicePolicy (
> +  IN PCI_IO_DEVICE          *PciDevice
> +  );
> +
> +/**
> +  Notifies the platform about the current PCI Express state of the device.
> +
> +  @param  PciDevice                 A pointer to PCI_IO_DEVICE
> +  @param  PciExDeviceConfiguration  Pointer to
> EFI_PCI_EXPRESS_DEVICE_CONFIGURATION.
> +                                    Used to pass the current state of device to
> +                                    platform.
> +
> +  @retval EFI_STATUS        The direct status from the PCI Express Platform
> Protocol
> +  @retval EFI_UNSUPPORTED   returns when the PCI Express Platform Protocol
> or its
> +                            alias PCI Express OVerride Protocol is not present.
> +**/
> +EFI_STATUS
> +PciExpressPlatformNotifyDeviceState (
> +  IN PCI_IO_DEVICE                        *PciDevice
> +  );
> +#endif
> --
> 2.21.0.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12] MdeModulePkg/PciBusDxe: Setup PCI Express init phase
       [not found] ` <15F137802DC889C4.7869@groups.io>
@ 2020-02-07 20:18   ` Javeed, Ashraf
  2020-02-10  7:37     ` Ni, Ray
  0 siblings, 1 reply; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:18 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch can also be viewed in the following repo:-
https://github.com/ashrafj/edk2-staging/commit/8c06ec777429cde1bddf368b16a886b3083ec12c

Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Saturday, February 8, 2020 1:35 AM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12]
> MdeModulePkg/PciBusDxe: Setup PCI Express init phase
> 
> References:-
>   https://bugzilla.tianocore.org/show_bug.cgi?id=1954
>   https://bugzilla.tianocore.org/show_bug.cgi?id=2194
>   https://bugzilla.tianocore.org/show_bug.cgi?id=2313
>   https://bugzilla.tianocore.org/show_bug.cgi?id=2499
>   https://bugzilla.tianocore.org/show_bug.cgi?id=2500
> 
> This code change represents the preparation of phase for initializing the PCI
> Express features at the end of PCI enumeration phase.
> 
> 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/PciDeviceSupport.c  | 181
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++-----------------------------------
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h |  23
> +++++++++++++++++++++++
>  2 files changed, 169 insertions(+), 35 deletions(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> index b7832c6..07ee9ba 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> @@ -1,7 +1,7 @@
>  /** @file
>    Supporting functions implementation for PCI devices management.
> 
> -Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
>  (C) Copyright 2018 Hewlett Packard Enterprise Development LP<BR>
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> @@ -597,7 +597,7 @@ DeRegisterPciDevice (  }
> 
>  /**
> -  Start to manage the PCI device on the specified root bridge or PCI-PCI Bridge.
> +  Start the PCI root Ports or PCI-PCI Bridge only.
> 
>    @param Controller          The root bridge handle.
>    @param RootBridge          A pointer to the PCI_IO_DEVICE.
> @@ -612,7 +612,82 @@ DeRegisterPciDevice (
> 
>  **/
>  EFI_STATUS
> -StartPciDevicesOnBridge (
> +EnablePciBridges (
> +  IN EFI_HANDLE                          Controller,
> +  IN PCI_IO_DEVICE                       *RootBridge
> +  )
> +
> +{
> +  PCI_IO_DEVICE             *PciIoDevice;
> +  EFI_STATUS                Status;
> +  LIST_ENTRY                *CurrentLink;
> +  UINT64                    Supports;
> +
> +  PciIoDevice = NULL;
> +  CurrentLink = RootBridge->ChildList.ForwardLink;
> +
> +  while (CurrentLink != NULL && CurrentLink != &RootBridge->ChildList)
> + {
> +
> +    PciIoDevice = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
> +
> +    //
> +    // check if the device has been assigned with required resource
> +    // and registered
> +    //
> +    if (!PciIoDevice->Registered && !PciIoDevice->Allocated) {
> +      return EFI_NOT_READY;
> +    }
> +
> +    if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> +      Status = EnablePciBridges (
> +                 Controller,
> +                 PciIoDevice
> +                 );
> +
> +      PciIoDevice->PciIo.Attributes (
> +                           &(PciIoDevice->PciIo),
> +                           EfiPciIoAttributeOperationSupported,
> +                           0,
> +                           &Supports
> +                         );
> +      Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> +      PciIoDevice->PciIo.Attributes (
> +                           &(PciIoDevice->PciIo),
> +                           EfiPciIoAttributeOperationEnable,
> +                           Supports,
> +                           NULL
> +                         );
> +
> +    }
> +
> +    CurrentLink = CurrentLink->ForwardLink;  }
> +
> +  if (PciIoDevice == NULL) {
> +    return EFI_NOT_FOUND;
> +  } else {
> +    return EFI_SUCCESS;
> +  }
> +}
> +
> +
> +/**
> +  Register to manage the PCI device on the specified root bridge or PCI-PCI
> Bridge.
> +
> +  @param Controller          The root bridge handle.
> +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> +  @param RemainingDevicePath A pointer to the
> EFI_DEVICE_PATH_PROTOCOL.
> +  @param NumberOfChildren    Children number.
> +  @param ChildHandleBuffer   A pointer to the child handle buffer.
> +
> +  @retval EFI_NOT_READY   Device is not allocated.
> +  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
> +  @retval EFI_NOT_FOUND   Can not find the specific device.
> +  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
> +
> +**/
> +EFI_STATUS
> +RegisterPciDevicesOnBridge (
>    IN EFI_HANDLE                          Controller,
>    IN PCI_IO_DEVICE                       *RootBridge,
>    IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
> @@ -626,7 +701,6 @@ StartPciDevicesOnBridge (
>    EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;
>    EFI_STATUS                Status;
>    LIST_ENTRY                *CurrentLink;
> -  UINT64                    Supports;
> 
>    PciIoDevice = NULL;
>    CurrentLink = RootBridge->ChildList.ForwardLink;
> @@ -681,7 +755,7 @@ StartPciDevicesOnBridge (
>        // If it is a PPB
>        //
>        if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> -        Status = StartPciDevicesOnBridge (
> +        Status = RegisterPciDevicesOnBridge (
>                     Controller,
>                     PciIoDevice,
>                     CurrentDevicePath,
> @@ -689,20 +763,6 @@ StartPciDevicesOnBridge (
>                     ChildHandleBuffer
>                     );
> 
> -        PciIoDevice->PciIo.Attributes (
> -                             &(PciIoDevice->PciIo),
> -                             EfiPciIoAttributeOperationSupported,
> -                             0,
> -                             &Supports
> -                             );
> -        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> -        PciIoDevice->PciIo.Attributes (
> -                             &(PciIoDevice->PciIo),
> -                             EfiPciIoAttributeOperationEnable,
> -                             Supports,
> -                             NULL
> -                             );
> -
>          return Status;
>        } else {
> 
> @@ -733,28 +793,13 @@ StartPciDevicesOnBridge (
>        }
> 
>        if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> -        Status = StartPciDevicesOnBridge (
> +        Status = RegisterPciDevicesOnBridge (
>                     Controller,
>                     PciIoDevice,
>                     RemainingDevicePath,
>                     NumberOfChildren,
>                     ChildHandleBuffer
>                     );
> -
> -        PciIoDevice->PciIo.Attributes (
> -                             &(PciIoDevice->PciIo),
> -                             EfiPciIoAttributeOperationSupported,
> -                             0,
> -                             &Supports
> -                             );
> -        Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
> -        PciIoDevice->PciIo.Attributes (
> -                             &(PciIoDevice->PciIo),
> -                             EfiPciIoAttributeOperationEnable,
> -                             Supports,
> -                             NULL
> -                             );
> -
>        }
> 
>        CurrentLink = CurrentLink->ForwardLink; @@ -768,6 +813,72 @@
> StartPciDevicesOnBridge (
>    }
>  }
> 
> +/**
> +  Start to manage the PCI device on the specified root bridge or PCI-PCI Bridge.
> +
> +  @param Controller          The root bridge handle.
> +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> +  @param RemainingDevicePath A pointer to the
> EFI_DEVICE_PATH_PROTOCOL.
> +  @param NumberOfChildren    Children number.
> +  @param ChildHandleBuffer   A pointer to the child handle buffer.
> +
> +  @retval EFI_NOT_READY   Device is not allocated.
> +  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.
> +  @retval EFI_NOT_FOUND   Can not find the specific device.
> +  @retval EFI_SUCCESS     Success to start Pci devices on bridge.
> +
> +**/
> +EFI_STATUS
> +StartPciDevicesOnBridge (
> +  IN EFI_HANDLE                          Controller,
> +  IN PCI_IO_DEVICE                       *RootBridge,
> +  IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,
> +  IN OUT UINT8                           *NumberOfChildren,
> +  IN OUT EFI_HANDLE                      *ChildHandleBuffer
> +  )
> +
> +{
> +  EFI_STATUS                Status;
> +
> +  //
> +  // first register all the PCI devices  //  Status =
> + RegisterPciDevicesOnBridge (
> +             Controller,
> +             RootBridge,
> +             RemainingDevicePath,
> +             NumberOfChildren,
> +             ChildHandleBuffer
> +             );
> +
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  } else {
> +    //
> +    // the late configuration of PCI Express features
> +    // the platform is required to indicate its requirement for the initialization
> +    // of PCI Express features by publishing its protocol
> +    //
> +    if (
> +        gFullEnumeration
> +        && IsPciExpressProtocolPresent ()
> +    ) {
> +
> +      Status = EnumeratePciExpressFeatures (
> +                Controller,
> +                RootBridge
> +                );
> +    }
> +    //
> +    // finally start those PCI bridge port devices only
> +    //
> +    return EnablePciBridges (
> +             Controller,
> +             RootBridge
> +             );
> +  }
> +}
> +
>  /**
>    Start to manage all the PCI devices it found previously under
>    the entire host bridge.
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> index 2eff8aa..9b7e51f 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> @@ -223,4 +223,27 @@ typedef struct {
>  }PCI_EXPRESS_FEATURE_INITIALIZATION_POINT;
> 
> 
> +
> +/**
> +  Enumerate all the nodes of the specified root bridge or PCI-PCI
> +Bridge, to
> +  configure the other PCI features.
> +
> +  @param RootBridge          A pointer to the PCI_IO_DEVICE.
> +
> +  @retval EFI_SUCCESS           The other PCI features configuration during
> enumeration
> +                                of all the nodes of the PCI root bridge instance were
> +                                programmed in PCI-compliance pattern along with the
> +                                device-specific policy, as applicable.
> +  @retval EFI_UNSUPPORTED       One of the override operation maong the
> nodes of
> +                                the PCI hierarchy resulted in a incompatible address
> +                                range.
> +  @retval EFI_INVALID_PARAMETER The override operation is performed with
> invalid input
> +                                parameters.
> +**/
> +EFI_STATUS
> +EnumeratePciExpressFeatures (
> +  IN EFI_HANDLE             Controller,
> +  IN PCI_IO_DEVICE          *RootBridge
> +  );
> +
>  #endif
> --
> 2.21.0.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12] PciBusDxe: New PCI Express feature Max_Payload_Size
       [not found] ` <15F137813D8F0C21.4848@groups.io>
@ 2020-02-07 20:19   ` Javeed, Ashraf
  0 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:19 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch can also be viewed in the following repo:-
https://github.com/ashrafj/edk2-staging/commit/5c835eb3a75da8a65198ba255442e112f0970f39

Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Saturday, February 8, 2020 1:35 AM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12]
> PciBusDxe: New PCI Express feature Max_Payload_Size
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> 
> The code changes are made to enable the configuration of new PCI Express
> feature Max_Payload_Size (MPS), which defines the data packet size for the PCI
> transactions, as per the PCI Base Specification 4 Revision 1.
> 
> The code changes are made to calibrate highest common value that is appl-
> icable to all the child nodes originating from the primary root bridge device
> instance.
> 
> This programming of MPS is based on each PCI device's capability, and also its
> device-specific platform policy obtained using the new PCI Express Platform
> Protocol interface, defined in the below feature request:-
> https://bugzilla.tianocore.org/show_bug.cgi?id=1954
> 
> 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/PciBusDxe.inf        |   2 ++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c | 193
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h |  55
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  |  22
> ++++++++++++++++------
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h  |   5 +++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c |  80
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h |  17
> +++++++++++++++++
>  8 files changed, 369 insertions(+), 6 deletions(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> index 225229d..5dc5f61 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> @@ -287,6 +287,7 @@ struct _PCI_IO_DEVICE {
>    // This field is used to support this case.
>    //
>    UINT16                                    BridgeIoAlignment;
> +  UINT8                                     SetupMPS;
>  };
> 
>  #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ diff --git
> a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> index f06b411..e3ad105 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> @@ -61,6 +61,8 @@
>    PciFeatureSupport.h
>    PciPlatformSupport.c
>    PciPlatformSupport.h
> +  PciExpressFeatures.c
> +  PciExpressFeatures.h
> 
>  [Packages]
>    MdePkg/MdePkg.dec
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> new file mode 100644
> index 0000000..6084446
> --- /dev/null
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> @@ -0,0 +1,193 @@
> +/** @file
> +  PCI standard feature support functions implementation for PCI Bus module..
> +
> +Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "PciBus.h"
> +#include "PciFeatureSupport.h"
> +
> +VOID
> +ReportPciWriteError (
> +  IN UINT8  Bus,
> +  IN UINT8  Device,
> +  IN UINT8  Function,
> +  IN UINT32 Offset
> +  )
> +{
> +  DEBUG ((
> +    DEBUG_ERROR,
> +    "Unexpected PCI register (%d,%d,%d,0x%x) write error!",
> +    Bus,
> +    Device,
> +    Function,
> +    Offset
> +    ));
> +}
> +
> +/**
> +  Compare and Swap the payload value - between the global variable to
> +maaintain
> +  common value among all the devices in the PCIe heirarchy from the
> +root bridge
> +  device and all its child devices; with the device-sepcific setup value.
> +
> +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> +  @param PciExpressConfigurationTable  pointer to
> + PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +
> +  @retval EFI_SUCCESS                   processing of PCI feature Max_Payload_Size
> +                                        is successful.
> +**/
> +EFI_STATUS
> +CasMaxPayloadSize (
> +    IN  PCI_IO_DEVICE                             *PciDevice,
> +    IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciExpressConfigurationTable
> +  )
> +{
> +  UINT8                                   MpsValue;
> +
> +  //
> +  // align the MPS of the tree to the HCF with this device  //  if
> + (PciExpressConfigurationTable) {
> +    MpsValue = PciExpressConfigurationTable->Max_Payload_Size;
> +
> +    MpsValue = MIN (PciDevice->SetupMPS, MpsValue);
> +    PciDevice->SetupMPS = MIN (PciDevice->SetupMPS, MpsValue);
> +
> +    if (MpsValue != PciExpressConfigurationTable->Max_Payload_Size) {
> +      PciExpressConfigurationTable->Max_Payload_Size = MpsValue;
> +    }
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "MPS: %d [DevCap:%d],",
> +    PciDevice->SetupMPS,
> + PciDevice->PciExpressCapabilityStructure.DeviceCapability.Bits.MaxPayl
> + oadSize
> +  ));
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  The main routine which process the PCI feature Max_Payload_Size as
> +per the
> +  device-specific platform policy, as well as in complaince with the
> +PCI Base
> +  specification Revision 4, that aligns the value for the entire PCI
> +heirarchy
> +  starting from its physical PCI Root port / Bridge device.
> +
> +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> +  @param PciExpressConfigurationTable  pointer to
> + PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +
> +  @retval EFI_SUCCESS                   processing of PCI feature Max_Payload_Size
> +                                        is successful.
> +**/
> +EFI_STATUS
> +SetupMaxPayloadSize (
> +  IN  PCI_IO_DEVICE                             *PciDevice,
> +  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciExpressConfigurationTable
> +  )
> +{
> +  PCI_REG_PCIE_DEVICE_CAPABILITY          PciDeviceCap;
> +  UINT8                                   MpsValue;
> +
> +
> +  PciDeviceCap.Uint32 =
> + PciDevice->PciExpressCapabilityStructure.DeviceCapability.Uint32;
> +
> +  if (PciDevice->SetupMPS == EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_AUTO) {
> +    //
> +    // configure this feature as per its PCIe device capabilities
> +    //
> +    MpsValue = (UINT8)PciDeviceCap.Bits.MaxPayloadSize;
> +    //
> +    // no change to PCI Root ports without any endpoint device
> +    //
> +    if (IS_PCI_BRIDGE (&PciDevice->Pci) && PciDeviceCap.Bits.MaxPayloadSize) {
> +      if (IsListEmpty  (&PciDevice->ChildList)) {
> +        //
> +        // No device on root bridge
> +        //
> +        MpsValue = PCIE_MAX_PAYLOAD_SIZE_128B;
> +      }
> +    }
> +  } else {
> +    MpsValue = SetDevicePolicyPciExpressMps (PciDevice->SetupMPS);  }
> + //  // discard device policy override request if greater than PCI
> + device capability  //  PciDevice->SetupMPS = MIN
> + ((UINT8)PciDeviceCap.Bits.MaxPayloadSize, MpsValue);
> +
> +  return CasMaxPayloadSize (
> +          PciDevice,
> +          PciExpressConfigurationTable
> +          );
> +}
> +
> +/**
> +  Overrides the PCI Device Control register MaxPayloadSize register
> +field; 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
> +ProgramMaxPayloadSize (
> +  IN PCI_IO_DEVICE          *PciDevice,
> +  IN VOID                   *PciExFeatureConfiguration
> +  )
> +{
> +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> +  UINT32                      Offset;
> +  EFI_STATUS                  Status;
> +  EFI_TPL                     OldTpl;
> +
> +  PcieDev.Uint16 = 0;
> +  Offset = PciDevice->PciExpressCapabilityOffset +
> +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> + Status = PciDevice->PciIo.Pci.Read (
> +                                  &PciDevice->PciIo,
> +                                  EfiPciIoWidthUint16,
> +                                  Offset,
> +                                  1,
> +                                  &PcieDev.Uint16
> +                                  );
> +  ASSERT (Status == EFI_SUCCESS);
> +
> +  if (PcieDev.Bits.MaxPayloadSize != PciDevice->SetupMPS) {
> +    PcieDev.Bits.MaxPayloadSize = PciDevice->SetupMPS;
> +    DEBUG (( DEBUG_INFO, "MPS=%d,", PciDevice->SetupMPS));
> +
> +    //
> +    // 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,
> +                                    &PcieDev.Uint16
> +                                    );
> +    //
> +    // Restore TPL to its original level
> +    //
> +    gBS->RestoreTPL (OldTpl);
> +
> +    if (!EFI_ERROR(Status)) {
> +      PciDevice->PciExpressCapabilityStructure.DeviceControl.Uint16 =
> PcieDev.Uint16;
> +    } else {
> +      ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber,
> PciDevice->FunctionNumber, Offset);
> +    }
> +  } else {
> +    DEBUG (( DEBUG_INFO, "No MPS=%d,", PciDevice->SetupMPS));  }
> +
> +  return Status;
> +}
> +
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> new file mode 100644
> index 0000000..460437b
> --- /dev/null
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> @@ -0,0 +1,55 @@
> +/** @file
> +  PCI standard feature support functions implementation for PCI Bus module..
> +
> +Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef _EFI_PCI_EXPRESS_FEATURES_H_
> +#define _EFI_PCI_EXPRESS_FEATURES_H_
> +
> +
> +/**
> +  The main routine which process the PCI feature Max_Payload_Size as
> +per the
> +  device-specific platform policy, as well as in complaince with the
> +PCI Base
> +  specification Revision 4, that aligns the value for the entire PCI
> +heirarchy
> +  starting from its physical PCI Root port / Bridge device.
> +
> +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> +  @param PciFeaturesConfigurationTable  pointer to
> + PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +
> +  @retval EFI_SUCCESS                   processing of PCI feature Max_Payload_Size
> +                                        is successful.
> +**/
> +EFI_STATUS
> +SetupMaxPayloadSize (
> +  IN  PCI_IO_DEVICE                             *PciDevice,
> +  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciFeaturesConfigurationTable
> +  );
> +
> +EFI_STATUS
> +CasMaxPayloadSize (
> +  IN  PCI_IO_DEVICE                             *PciDevice,
> +  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciFeaturesConfigurationTable
> +  );
> +
> +/**
> +  Overrides the PCI Device Control register Max_Read_Req_Size register
> +field; 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
> controller.
> +  @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
> +ProgramMaxPayloadSize (
> +  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 3980a8e..aae6139 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> @@ -8,6 +8,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #include "PciBus.h"
>  #include "PciFeatureSupport.h"
> +#include "PciExpressFeatures.h"
> 
>  /**
>    Hold the current instance of Root Bridge IO protocol Handle
> @@ -29,7 +30,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY
> mPciExpressPlatformPolicy = {
>      //
>      // support for PCI Express feature - Max. Payload Size
>      //
> -    FALSE,
> +    TRUE,
>      //
>      // support for PCI Express feature - Max. Read Request Size
>      //
> @@ -94,11 +95,16 @@ BOOLEAN   mPciExpressGetPlatformPolicyComplete =
> FALSE;
>  // PCI Express feature initialization phase handle routines  //
> PCI_EXPRESS_FEATURE_INITIALIZATION_POINT
> mPciExpressFeatureInitializationList[] = {
> -    //
> -    // vacant entry, shall be replaced with actual entry when the PCI Express
> -    // feature are added.
> -    //
> -  { 0, 0, NULL}
> +
> +  {
> +    PciExpressFeatureSetupPhase,          PciExpressMps,
> SetupMaxPayloadSize
> +  },
> +  {
> +    PciExpressFeatureEntendedSetupPhase,  PciExpressMps,
> CasMaxPayloadSize
> +  },
> +  {
> +    PciExpressFeatureProgramPhase,        PciExpressMps,
> ProgramMaxPayloadSize
> +  }
>  };
> 
>  /**
> @@ -597,6 +603,10 @@ CreatePciRootBridgeDeviceNode (
>                       );
>    if (PciConfigTable) {
>      PciConfigTable->ID                          = PortNumber;
> +    //
> +    // start by assuming 4096B as the default value for the Max. Payload Size
> +    //
> +    PciConfigTable->Max_Payload_Size            =
> PCIE_MAX_PAYLOAD_SIZE_4096B;
>    }
> 
>    RootBridgeNode->PciExFeaturesConfigurationTable  = PciConfigTable; diff --
> git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> index 9b7e51f..4ecbefc 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> @@ -66,6 +66,11 @@ struct
> _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE {
>    // Configuration Table ID
>    //
>    UINTN                                     ID;
> +  //
> +  // to configure the PCI feature Maximum payload size to maintain the
> + data packet  // size among all the PCI devices in the PCI hierarchy
> + //
> +  UINT8                                     Max_Payload_Size;
>  };
> 
>  //
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> index 31c675d..3e9d4c5 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> @@ -81,6 +81,39 @@ IsPciExpressProtocolPresent (
>    return TRUE;
>  }
> 
> +/**
> +  Routine to translate the given device-specific platform policy from
> +type
> +  EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE to HW-specific value, as per PCI
> +Base Specification
> +  Revision 4.0; for the PCI feature Max_Payload_Size.
> +
> +  @param  MPS     Input device-specific policy should be in terms of type
> +                  EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE
> +
> +  @retval         Range values for the Max_Payload_Size as defined in the PCI
> +                  Base Specification 4.0 **/
> +UINT8
> +SetDevicePolicyPciExpressMps (
> +  IN  UINT8                   MPS
> +)
> +{
> +  switch (MPS) {
> +    case EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_128B:
> +      return PCIE_MAX_PAYLOAD_SIZE_128B;
> +    case EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_256B:
> +      return PCIE_MAX_PAYLOAD_SIZE_256B;
> +    case EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_512B:
> +      return PCIE_MAX_PAYLOAD_SIZE_512B;
> +    case EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_1024B:
> +      return PCIE_MAX_PAYLOAD_SIZE_1024B;
> +    case EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_2048B:
> +      return PCIE_MAX_PAYLOAD_SIZE_2048B;
> +    case EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_4096B:
> +      return PCIE_MAX_PAYLOAD_SIZE_4096B;
> +    default:
> +      return PCIE_MAX_PAYLOAD_SIZE_128B;
> +  }
> +}
> 
>  /**
>    Generic routine to setup the PCI features as per its predetermined defaults.
> @@ -91,6 +124,12 @@ SetupDefaultPciExpressDevicePolicy (
>    )
>  {
> 
> +  if (mPciExpressPlatformPolicy.Mps) {
> +    PciDevice->SetupMPS = EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_AUTO;
> +  } else {
> +    PciDevice->SetupMPS = EFI_PCI_EXPRESS_NOT_APPLICABLE;  }
> +
>  }
> 
>  /**
> @@ -163,6 +202,15 @@ GetPciExpressDevicePolicy (
>      // platform chipset policies are returned for this PCI device
>      //
> 
> +    //
> +    // set device specific policy for the Max_Payload_Size
> +    //
> +    if (mPciExpressPlatformPolicy.Mps) {
> +      PciDevice->SetupMPS = PciExpressDevicePolicy.DeviceCtlMPS;
> +    } else {
> +      PciDevice->SetupMPS = EFI_PCI_EXPRESS_NOT_APPLICABLE;
> +    }
> +
> 
>      DEBUG ((
>        DEBUG_INFO,
> @@ -257,6 +305,28 @@ PciExpressPlatformGetPolicy (
>    return Status;
>  }
> 
> +EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE
> +GetPciExpressMps (
> +  IN UINT8              Mps
> +  )
> +{
> +  switch (Mps) {
> +    case PCIE_MAX_PAYLOAD_SIZE_128B:
> +      return EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_128B;
> +    case PCIE_MAX_PAYLOAD_SIZE_256B:
> +      return EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_256B;
> +    case PCIE_MAX_PAYLOAD_SIZE_512B:
> +      return EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_512B;
> +    case PCIE_MAX_PAYLOAD_SIZE_1024B:
> +      return EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_1024B;
> +    case PCIE_MAX_PAYLOAD_SIZE_2048B:
> +      return EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_2048B;
> +    case PCIE_MAX_PAYLOAD_SIZE_4096B:
> +      return EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_4096B;
> +  }
> +  return EFI_PCI_EXPRESS_NOT_APPLICABLE; }
> +
> 
>  /**
>    Notifies the platform about the current PCI Express state of the device.
> @@ -277,6 +347,16 @@ PciExpressPlatformNotifyDeviceState (  {
>    EFI_PCI_EXPRESS_DEVICE_CONFIGURATION      PciExDeviceConfiguration;
> 
> +  //
> +  // get the device-specific state for the PCIe Max_Payload_Size
> + feature  //  if (mPciExpressPlatformPolicy.Mps) {
> +    PciExDeviceConfiguration.DeviceCtlMPS = GetPciExpressMps (
> +                                              (UINT8)PciDevice-
> >PciExpressCapabilityStructure.DeviceControl.Bits.MaxPayloadSize
> +                                              );  } else {
> +    PciExDeviceConfiguration.DeviceCtlMPS =
> + EFI_PCI_EXPRESS_NOT_APPLICABLE;  }
> 
>    if (mPciExPlatformProtocol != NULL) {
>      return mPciExPlatformProtocol->NotifyDeviceState ( diff --git
> a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> index 4283b81..5ae6386 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> @@ -84,4 +84,21 @@ EFI_STATUS
>  PciExpressPlatformNotifyDeviceState (
>    IN PCI_IO_DEVICE                        *PciDevice
>    );
> +
> +/**
> +  Routine to translate the given device-specific platform policy from
> +type
> +  EFI_PCI_CONF_MAX_PAYLOAD_SIZE to HW-specific value, as per PCI Base
> +Specification
> +  Revision 4.0; for the PCI feature Max_Payload_Size.
> +
> +  @param  MPS     Input device-specific policy should be in terms of type
> +                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
> +
> +  @retval         Range values for the Max_Payload_Size as defined in the PCI
> +                  Base Specification 4.0 **/
> +UINT8
> +SetDevicePolicyPciExpressMps (
> +  IN  UINT8                   MPS
> +);
> +
>  #endif
> --
> 2.21.0.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 04/12] PciBusDxe: New PCI Express feature Max_Read_Req_Size
       [not found] ` <15F13782B6D7AE2E.15938@groups.io>
@ 2020-02-07 20:20   ` Javeed, Ashraf
  0 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:20 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch can also be viewed in the following repo:-
https://github.com/ashrafj/edk2-staging/commit/91e85bdb96600e72d5d7ab4d170089abcf1fe4fb

Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Saturday, February 8, 2020 1:35 AM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 04/12]
> PciBusDxe: New PCI Express feature Max_Read_Req_Size
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> 
> The code changes are made to enable the configuration of PCI Express feature
> Max_Read_Req_Size (MRRS), which defines the memory read request size for
> the PCI transactions, as per the PCI Base Specification 4 Revision 1.
> 
> The code changes are made to configure a common value that is applicable to
> all the child nodes originating from the root bridge device instance, based on
> following 3 criteria:-
> (1) if platform defines MRRS device policy for any one PCI device in the
>      tree than align all the devices in the PCI tree to that same value
> (2) if platform does not provide device policy for any of the devices in
>     the PCI tree than setup the MRRS value equivalent to MPS value for
>     all PCI devices to meet the criteria for the isochronous traffic
> (3) if platform does not provide device policy for any of the devices and
>     it has not selected the MPS to be configured either; than the config-
>     uration of the MRRS is performed based on highest common value of the
>     MPS advertized in the PCI device capability registers of the devices
> 
> This programming of MRRS gets the device-specific platform policy using the
> new PCI Express Platform Protocol interface, defined in the below feature
> request:- https://bugzilla.tianocore.org/show_bug.cgi?id=1954
> 
> 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 | 190
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h |  45
> +++++++++++++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  |  20
> +++++++++++++++++++-
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h  |   9 +++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c |  81
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h |  15
> +++++++++++++++
>  7 files changed, 360 insertions(+), 1 deletion(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> index 5dc5f61..77b44c0 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> @@ -288,6 +288,7 @@ struct _PCI_IO_DEVICE {
>    //
>    UINT16                                    BridgeIoAlignment;
>    UINT8                                     SetupMPS;
> +  UINT8                                     SetupMRRS;
>  };
> 
>  #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 6084446..2810158 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> @@ -191,3 +191,193 @@ ProgramMaxPayloadSize (
>    return Status;
>  }
> 
> +EFI_STATUS
> +ConditionalCasMaxReadReqSize (
> +  IN  PCI_IO_DEVICE                             *PciDevice,
> +  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciExpressConfigurationTable
> +  )
> +{
> +  //
> +  // align the Max_Read_Request_Size of the PCI tree based on 3 conditions:
> +  // first, if user defines MRRS for any one PCI device in the tree
> +than align
> +  // all the devices in the PCI tree.
> +  // second, if user override is not define for this PCI tree than
> +setup the MRRS
> +  // based on MPS value of the tree to meet the criteria for the
> +isochronous
> +  // traffic.
> +  // third, if no user override, or platform firmware policy has not
> +selected
> +  // this PCI bus driver to configure the MPS; than configure the MRRS
> +to a
> +  // highest common value of PCI device capability for the MPS found
> +among all
> +  // the PCI devices in this tree
> +  //
> +  if (PciExpressConfigurationTable) {
> +    if (PciExpressConfigurationTable->Lock_Max_Read_Request_Size) {
> +      PciDevice->SetupMRRS = PciExpressConfigurationTable-
> >Max_Read_Request_Size;
> +    } else {
> +      if (mPciExpressPlatformPolicy.Mps) {
> +        PciDevice->SetupMRRS = PciDevice->SetupMPS;
> +      } else {
> +        PciDevice->SetupMRRS = MIN (
> +                                PciDevice->SetupMRRS,
> +                                PciExpressConfigurationTable->Max_Read_Request_Size
> +                                );
> +      }
> +      PciExpressConfigurationTable->Max_Read_Request_Size = PciDevice-
> >SetupMRRS;
> +    }
> +  }
> +  DEBUG (( DEBUG_INFO, "MRRS: %d,", PciDevice->SetupMRRS));
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  The main routine which process the PCI feature Max_Read_Req_Size as
> +per the
> +  device-specific platform policy, as well as in complaince with the
> +PCI Base
> +  specification Revision 4, that aligns the value for the entire PCI
> +heirarchy
> +  starting from its physical PCI Root port / Bridge device.
> +
> +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> +  @param PciExpressConfigurationTable  pointer to
> + PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +
> +  @retval EFI_SUCCESS                   processing of PCI feature
> Max_Read_Req_Size
> +                                        is successful.
> +**/
> +EFI_STATUS
> +SetupMaxReadReqSize (
> +  IN  PCI_IO_DEVICE                           *PciDevice,
> +  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciExpressConfigurationTable
> +  )
> +{
> +  PCI_REG_PCIE_DEVICE_CAPABILITY  PciDeviceCap;
> +  UINT8                           MrrsValue;
> +
> +  PciDeviceCap.Uint32 =
> + PciDevice->PciExpressCapabilityStructure.DeviceCapability.Uint32;
> +
> +  if (PciDevice->SetupMRRS == EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_AUTO)
> {
> +    //
> +    // The maximum read request size is not the data packet size of the TLP,
> +    // but the memory read request size, and set to the function as a requestor
> +    // to not exceed this limit.
> +    // However, for the PCI device capable of isochronous traffic; this memory
> read
> +    // request size should not extend beyond the Max_Payload_Size. Thus, in
> case if
> +    // device policy return by platform indicates to set as per device capability
> +    // than set as per Max_Payload_Size configuration value
> +    //
> +    if (mPciExpressPlatformPolicy.Mps) {
> +      MrrsValue = PciDevice->SetupMPS;
> +    } else {
> +      //
> +      // in case this driver is not required to configure the Max_Payload_Size
> +      // than consider programming HCF of the device capability's
> Max_Payload_Size
> +      // in this PCI hierarchy; thus making this an implementation specific feature
> +      // which the platform should avoid. For better results, the platform should
> +      // make both the Max_Payload_Size & Max_Read_Request_Size to be
> configured
> +      // by this driver
> +      //
> +      MrrsValue = (UINT8)PciDeviceCap.Bits.MaxPayloadSize;
> +    }
> +  } else {
> +    //
> +    // override as per platform based device policy
> +    //
> +    MrrsValue = SetDevicePolicyPciExpressMrrs (PciDevice->SetupMRRS);
> +    //
> +    // align this device's Max_Read_Request_Size value to the entire PCI tree
> +    //
> +    if (PciExpressConfigurationTable) {
> +      if (!PciExpressConfigurationTable->Lock_Max_Read_Request_Size) {
> +        PciExpressConfigurationTable->Lock_Max_Read_Request_Size = TRUE;
> +        PciExpressConfigurationTable->Max_Read_Request_Size = MrrsValue;
> +      } else {
> +        //
> +        // in case of another user enforced value of MRRS within the same tree,
> +        // pick the smallest between the locked value and this value; to set
> +        // across entire PCI tree nodes
> +        //
> +        MrrsValue = MIN (
> +                      MrrsValue,
> +                      PciExpressConfigurationTable->Max_Read_Request_Size
> +                      );
> +        PciExpressConfigurationTable->Max_Read_Request_Size = MrrsValue;
> +      }
> +    }
> +  }
> +  //
> +  // align this device's Max_Read_Request_Size to derived configuration
> + value  //  PciDevice->SetupMRRS = MrrsValue;
> +
> +  return ConditionalCasMaxReadReqSize (
> +          PciDevice,
> +          PciExpressConfigurationTable
> +          );
> +}
> +
> +
> +/**
> +  Overrides the PCI Device Control register Max_Read_Req_Size register
> +field; 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
> controller.
> +  @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
> +ProgramMaxReadReqSize (
> +  IN PCI_IO_DEVICE          *PciDevice,
> +  IN VOID                   *PciExFeatureConfiguration
> +  )
> +{
> +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> +  UINT32                      Offset;
> +  EFI_STATUS                  Status;
> +  EFI_TPL                     OldTpl;
> +
> +  PcieDev.Uint16 = 0;
> +  Offset = PciDevice->PciExpressCapabilityOffset +
> +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> + Status = PciDevice->PciIo.Pci.Read (
> +                                  &PciDevice->PciIo,
> +                                  EfiPciIoWidthUint16,
> +                                  Offset,
> +                                  1,
> +                                  &PcieDev.Uint16
> +                                  );
> +  ASSERT (Status == EFI_SUCCESS);
> +
> +  if (PcieDev.Bits.MaxReadRequestSize != PciDevice->SetupMRRS) {
> +    PcieDev.Bits.MaxReadRequestSize = PciDevice->SetupMRRS;
> +    DEBUG (( DEBUG_INFO, "MRRS: %d,", PciDevice->SetupMRRS));
> +
> +    //
> +    // 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,
> +                                    &PcieDev.Uint16
> +                                    );
> +    //
> +    // Restore TPL to its original level
> +    //
> +    gBS->RestoreTPL (OldTpl);
> +
> +    if (!EFI_ERROR(Status)) {
> +      PciDevice->PciExpressCapabilityStructure.DeviceControl.Uint16 =
> PcieDev.Uint16;
> +    } else {
> +      ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber,
> PciDevice->FunctionNumber, Offset);
> +    }
> +  } else {
> +    DEBUG (( DEBUG_INFO, "No MRRS=%d,", PciDevice->SetupMRRS));  }
> +
> +  return Status;
> +}
> +
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> index 460437b..b43fba7 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> @@ -52,4 +52,49 @@ ProgramMaxPayloadSize (
>    IN VOID                   *PciExFeatureConfiguration
>    );
> 
> +
> +EFI_STATUS
> +ConditionalCasMaxReadReqSize (
> +  IN  PCI_IO_DEVICE                             *PciDevice,
> +  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciFeaturesConfigurationTable
> +  );
> +
> +/**
> +  The main routine which process the PCI feature Max_Read_Req_Size as
> +per the
> +  device-specific platform policy, as well as in complaince with the
> +PCI Base
> +  specification Revision 4, that aligns the value for the entire PCI
> +heirarchy
> +  starting from its physical PCI Root port / Bridge device.
> +
> +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> +  @param PciConfigPhase                 for the PCI feature configuration phases:
> +                                        PciExpressFeatureSetupPhase &
> + PciExpressFeatureEntendedSetupPhase
> +  @param PciFeaturesConfigurationTable  pointer to
> + PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +
> +  @retval EFI_SUCCESS                   processing of PCI feature
> Max_Read_Req_Size
> +                                        is successful.
> +**/
> +EFI_STATUS
> +SetupMaxReadReqSize (
> +  IN  PCI_IO_DEVICE                           *PciDevice,
> +  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciFeaturesConfigurationTable
> +  );
> +
> +/**
> +  Overrides the PCI Device Control register Max_Read_Req_Size register
> +field; 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
> controller.
> +  @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
> +ProgramMaxReadReqSize (
> +  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 aae6139..1caf1f4 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> @@ -34,7 +34,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY
> mPciExpressPlatformPolicy = {
>      //
>      // support for PCI Express feature - Max. Read Request Size
>      //
> -    FALSE,
> +    TRUE,
>      //
>      // support for PCI Express feature - Extended Tag
>      //
> @@ -104,6 +104,15 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT
> mPciExpressFeatureInitializationList[]
>    },
>    {
>      PciExpressFeatureProgramPhase,        PciExpressMps,
> ProgramMaxPayloadSize
> +  },
> +  {
> +    PciExpressFeatureSetupPhase,          PciExpressMrrs,
> SetupMaxReadReqSize
> +  },
> +  {
> +    PciExpressFeatureEntendedSetupPhase,  PciExpressMrrs,
> ConditionalCasMaxReadReqSize
> +  },
> +  {
> +    PciExpressFeatureProgramPhase,        PciExpressMrrs,
> ProgramMaxReadReqSize
>    }
>  };
> 
> @@ -607,6 +616,15 @@ CreatePciRootBridgeDeviceNode (
>      // start by assuming 4096B as the default value for the Max. Payload Size
>      //
>      PciConfigTable->Max_Payload_Size            =
> PCIE_MAX_PAYLOAD_SIZE_4096B;
> +    //
> +    // start by assuming 4096B as the default value for the Max. Read Request
> Size
> +    //
> +    PciConfigTable->Max_Read_Request_Size       =
> PCIE_MAX_READ_REQ_SIZE_4096B;
> +    //
> +    // start by assuming the Max. Read Request Size need not be common for all
> +    // the devices in the PCI tree
> +    //
> +    PciConfigTable->Lock_Max_Read_Request_Size  = FALSE;
>    }
> 
>    RootBridgeNode->PciExFeaturesConfigurationTable  = PciConfigTable; diff --
> git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> index 4ecbefc..a1fc39c 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> @@ -71,6 +71,15 @@ struct
> _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE {
>    // size among all the PCI devices in the PCI hierarchy
>    //
>    UINT8                                     Max_Payload_Size;
> +  //
> +  // to configure the PCI feature maximum read request size to maintain
> + the memory  // requester size among all the PCI devices in the PCI
> + hierarchy  //
> +  UINT8                                     Max_Read_Request_Size;
> +  //
> +  // lock the Max_Read_Request_Size for the entire PCI tree of a root
> + port  //
> +  BOOLEAN                                   Lock_Max_Read_Request_Size;
>  };
> 
>  //
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> index 3e9d4c5..f74e566 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> @@ -115,6 +115,40 @@ SetDevicePolicyPciExpressMps (
>    }
>  }
> 
> +/**
> +  Routine to translate the given device-specific platform policy from
> +type
> +  EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE to HW-specific value, as per PCI
> +Base Specification
> +  Revision 4.0; for the PCI feature Max_Read_Req_Size.
> +
> +  @param  MRRS    Input device-specific policy should be in terms of type
> +                  EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE
> +
> +  @retval         Range values for the Max_Read_Req_Size as defined in the PCI
> +                  Base Specification 4.0 **/
> +UINT8
> +SetDevicePolicyPciExpressMrrs (
> +  IN  UINT8                   MRRS
> +)
> +{
> +  switch (MRRS) {
> +    case EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_128B:
> +      return PCIE_MAX_READ_REQ_SIZE_128B;
> +    case EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_256B:
> +      return PCIE_MAX_READ_REQ_SIZE_256B;
> +    case EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_512B:
> +      return PCIE_MAX_READ_REQ_SIZE_512B;
> +    case EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_1024B:
> +      return PCIE_MAX_READ_REQ_SIZE_1024B;
> +    case EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_2048B:
> +      return PCIE_MAX_READ_REQ_SIZE_2048B;
> +    case EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_4096B:
> +      return PCIE_MAX_READ_REQ_SIZE_4096B;
> +    default:
> +      return PCIE_MAX_READ_REQ_SIZE_128B;
> +  }
> +}
> +
>  /**
>    Generic routine to setup the PCI features as per its predetermined defaults.
>  **/
> @@ -130,6 +164,12 @@ SetupDefaultPciExpressDevicePolicy (
>      PciDevice->SetupMPS = EFI_PCI_EXPRESS_NOT_APPLICABLE;
>    }
> 
> +  if (mPciExpressPlatformPolicy.Mrrs) {
> +    PciDevice->SetupMRRS = EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_AUTO;
> +  } else {
> +    PciDevice->SetupMRRS = EFI_PCI_EXPRESS_NOT_APPLICABLE;  }
> +
>  }
> 
>  /**
> @@ -211,6 +251,14 @@ GetPciExpressDevicePolicy (
>        PciDevice->SetupMPS = EFI_PCI_EXPRESS_NOT_APPLICABLE;
>      }
> 
> +    //
> +    // set device specific policy for Max_Read_Req_Size
> +    //
> +    if (mPciExpressPlatformPolicy.Mrrs) {
> +      PciDevice->SetupMRRS = PciExpressDevicePolicy.DeviceCtlMRRS;
> +    } else {
> +      PciDevice->SetupMRRS = EFI_PCI_EXPRESS_NOT_APPLICABLE;
> +    }
> 
>      DEBUG ((
>        DEBUG_INFO,
> @@ -327,6 +375,28 @@ GetPciExpressMps (
>    return EFI_PCI_EXPRESS_NOT_APPLICABLE;  }
> 
> +EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE
> +GetPciExpressMrrs (
> +  IN UINT8              Mrrs
> +  )
> +{
> +  switch (Mrrs) {
> +    case PCIE_MAX_READ_REQ_SIZE_128B:
> +      return EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_128B;
> +    case PCIE_MAX_READ_REQ_SIZE_256B:
> +      return EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_256B;
> +    case PCIE_MAX_READ_REQ_SIZE_512B:
> +      return EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_512B;
> +    case PCIE_MAX_READ_REQ_SIZE_1024B:
> +      return EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_1024B;
> +    case PCIE_MAX_READ_REQ_SIZE_2048B:
> +      return EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_2048B;
> +    case PCIE_MAX_READ_REQ_SIZE_4096B:
> +      return EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_4096B;
> +  }
> +  return EFI_PCI_EXPRESS_NOT_APPLICABLE; }
> +
> 
>  /**
>    Notifies the platform about the current PCI Express state of the device.
> @@ -358,6 +428,17 @@ PciExpressPlatformNotifyDeviceState (
>      PciExDeviceConfiguration.DeviceCtlMPS =
> EFI_PCI_EXPRESS_NOT_APPLICABLE;
>    }
> 
> +  //
> +  // get the device-specific state for the PCIe Max_Read_Req_Size
> + feature  //  if (mPciExpressPlatformPolicy.Mrrs) {
> +    PciExDeviceConfiguration.DeviceCtlMRRS = GetPciExpressMrrs (
> +                                              (UINT8)PciDevice-
> >PciExpressCapabilityStructure.DeviceControl.Bits.MaxReadRequestSize
> +                                              );  } else {
> +    PciExDeviceConfiguration.DeviceCtlMRRS =
> + EFI_PCI_EXPRESS_NOT_APPLICABLE;  }
> +
>    if (mPciExPlatformProtocol != NULL) {
>      return mPciExPlatformProtocol->NotifyDeviceState (
>                                      mPciExPlatformProtocol, diff --git
> a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> index 5ae6386..4653c79 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> @@ -101,4 +101,19 @@ SetDevicePolicyPciExpressMps (
>    IN  UINT8                   MPS
>  );
> 
> +/**
> +  Routine to translate the given device-specific platform policy from
> +type
> +  EFI_PCI_CONF_MAX_READ_REQ_SIZE to HW-specific value, as per PCI Base
> +Specification
> +  Revision 4.0; for the PCI feature Max_Read_Req_Size.
> +
> +  @param  MRRS    Input device-specific policy should be in terms of type
> +                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
> +
> +  @retval         Range values for the Max_Read_Req_Size as defined in the PCI
> +                  Base Specification 4.0 **/
> +UINT8
> +SetDevicePolicyPciExpressMrrs (
> +  IN  UINT8                   MRRS
> +);
>  #endif
> --
> 2.21.0.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: New PCI Express feature Relax Ordering
       [not found] ` <15F1378301D514E4.15938@groups.io>
@ 2020-02-07 20:21   ` Javeed, Ashraf
  0 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:21 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch can also be viewed in the following repo:-
https://github.com/ashrafj/edk2-staging/commit/27d11f3bbba23ff8b55d67da3cc50f8ee6029103

Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Saturday, February 8, 2020 1:35 AM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12]
> PciBusDxe: New PCI Express feature Relax Ordering
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2313
> 
> The code changes are made to enable the configuration of PCI Express feature
> Relax Ordering (OR), that enables the PCI function to initiate requests if it does
> not require strong write ordering for its transact- ions; as per the PCI Express
> Base Specification 4 Revision 1.
> 
> 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.
> 
> 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             |  4 ++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c | 70
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h | 18
> ++++++++++++++++++  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> |  5 ++++-  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 61
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 157 insertions(+), 1 deletion(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> index 77b44c0..d3d795d 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> @@ -287,8 +287,12 @@ struct _PCI_IO_DEVICE {
>    // This field is used to support this case.
>    //
>    UINT16                                    BridgeIoAlignment;
> +  //
> +  // PCI Express features setup flags
> +  //
>    UINT8                                     SetupMPS;
>    UINT8                                     SetupMRRS;
> +  PCI_FEATURE_POLICY                        SetupRO;
>  };
> 
>  #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 2810158..3262b76 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> @@ -381,3 +381,73 @@ ProgramMaxReadReqSize (
>    return Status;
>  }
> 
> +/**
> +  Overrides the PCI Device Control register Relax Order register field;
> +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
> +ProgramRelaxOrder (
> +  IN PCI_IO_DEVICE          *PciDevice,
> +  IN VOID                   *PciExFeatureConfiguration
> +  )
> +{
> +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> +  UINT32                      Offset;
> +  EFI_STATUS                  Status;
> +  EFI_TPL                     OldTpl;
> +
> +  PcieDev.Uint16 = 0;
> +  Offset = PciDevice->PciExpressCapabilityOffset +
> +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> + Status = PciDevice->PciIo.Pci.Read (
> +                                  &PciDevice->PciIo,
> +                                  EfiPciIoWidthUint16,
> +                                  Offset,
> +                                  1,
> +                                  &PcieDev.Uint16
> +                                  );
> +  ASSERT (Status == EFI_SUCCESS);
> +
> +  if (PciDevice->SetupRO.Override
> +      &&  PcieDev.Bits.RelaxedOrdering != PciDevice->SetupRO.Act
> +      ) {
> +    PcieDev.Bits.RelaxedOrdering = PciDevice->SetupRO.Act;
> +    DEBUG (( DEBUG_INFO, "RO=%d,", PciDevice->SetupRO.Act));
> +
> +    //
> +    // 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,
> +                                    &PcieDev.Uint16
> +                                    );
> +    //
> +    // Restore TPL to its original level
> +    //
> +    gBS->RestoreTPL (OldTpl);
> +
> +    if (!EFI_ERROR(Status)) {
> +      PciDevice->PciExpressCapabilityStructure.DeviceControl.Uint16 =
> PcieDev.Uint16;
> +    } else {
> +      ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber,
> PciDevice->FunctionNumber, Offset);
> +    }
> +  } else {
> +    DEBUG (( DEBUG_INFO, "No RO,", PciDevice->SetupRO.Act));  }
> +
> +  return Status;
> +}
> +
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> index b43fba7..0d17801 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> @@ -97,4 +97,22 @@ ProgramMaxReadReqSize (
>    IN VOID                   *PciExFeatureConfiguration
>    );
> 
> +/**
> +  Overrides the PCI Device Control register Relax Order register field;
> +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
> +ProgramRelaxOrder (
> +  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 1caf1f4..267f570 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> @@ -42,7 +42,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY
> mPciExpressPlatformPolicy = {
>      //
>      // support for PCI Express feature - Relax Order
>      //
> -    FALSE,
> +    TRUE,
>      //
>      // support for PCI Express feature - No-Snoop
>      //
> @@ -113,6 +113,9 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT
> mPciExpressFeatureInitializationList[]
>    },
>    {
>      PciExpressFeatureProgramPhase,        PciExpressMrrs,
> ProgramMaxReadReqSize
> +  },
> +  {
> +    PciExpressFeatureProgramPhase,        PciExpressRelaxOrder,
> ProgramRelaxOrder
>    }
>  };
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> index f74e566..40eb8a3 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> @@ -149,6 +149,45 @@ SetDevicePolicyPciExpressMrrs (
>    }
>  }
> 
> +/**
> +  Routine to set the device-specific policy for the PCI feature Relax
> +Ordering
> +
> +  @param  RelaxOrder    value corresponding to data type
> EFI_PCI_EXPRESS_RELAX_ORDER
> +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> +**/
> +VOID
> +SetDevicePolicyPciExpressRo (
> +  IN  EFI_PCI_EXPRESS_RELAX_ORDER RelaxOrder,
> +  OUT PCI_IO_DEVICE               *PciDevice
> +  )
> +{
> +  //
> +  // implementation specific rules for the usage of PCI_FEATURE_POLICY
> +members
> +  // exclusively for the PCI Feature Relax Ordering (RO)
> +  //
> +  // .Override = 0 to skip this PCI feature RO for the PCI device
> +  // .Override = 1 to program this RO PCI feature
> +  //      .Act = 1 to enable the RO in the PCI device
> +  //      .Act = 0 to disable the RO in the PCI device
> +  //
> +  switch (RelaxOrder) {
> +    case  EFI_PCI_EXPRESS_RO_AUTO:
> +      PciDevice->SetupRO.Override = 0;
> +      break;
> +    case  EFI_PCI_EXPRESS_RO_DISABLE:
> +      PciDevice->SetupRO.Override = 1;
> +      PciDevice->SetupRO.Act = 0;
> +      break;
> +    case  EFI_PCI_EXPRESS_RO_ENABLE:
> +      PciDevice->SetupRO.Override = 1;
> +      PciDevice->SetupRO.Act = 1;
> +      break;
> +    default:
> +      PciDevice->SetupRO.Override = 0;
> +      break;
> +  }
> +}
> +
>  /**
>    Generic routine to setup the PCI features as per its predetermined defaults.
>  **/
> @@ -170,6 +209,8 @@ SetupDefaultPciExpressDevicePolicy (
>      PciDevice->SetupMRRS = EFI_PCI_EXPRESS_NOT_APPLICABLE;
>    }
> 
> +  PciDevice->SetupRO.Override = 0;
> +
>  }
> 
>  /**
> @@ -259,6 +300,15 @@ GetPciExpressDevicePolicy (
>      } else {
>        PciDevice->SetupMRRS = EFI_PCI_EXPRESS_NOT_APPLICABLE;
>      }
> +    //
> +    // set device specific policy for Relax Ordering
> +    //
> +    if (mPciExpressPlatformPolicy.RelaxOrder) {
> +      SetDevicePolicyPciExpressRo (PciExpressDevicePolicy.DeviceCtlRelaxOrder,
> PciDevice);
> +    } else {
> +      PciDevice->SetupRO.Override = 0;
> +    }
> +
> 
>      DEBUG ((
>        DEBUG_INFO,
> @@ -438,6 +488,17 @@ PciExpressPlatformNotifyDeviceState (
>    } else {
>      PciExDeviceConfiguration.DeviceCtlMRRS =
> EFI_PCI_EXPRESS_NOT_APPLICABLE;
>    }
> +  //
> +  // get the device-specific state for the PCIe Relax Order feature  //
> + if (mPciExpressPlatformPolicy.RelaxOrder) {
> +    PciExDeviceConfiguration.DeviceCtlRelaxOrder = PciDevice-
> >PciExpressCapabilityStructure.DeviceControl.Bits.RelaxedOrdering
> +                                                      ? EFI_PCI_EXPRESS_RO_ENABLE
> +                                                      :
> + EFI_PCI_EXPRESS_RO_DISABLE;  } else {
> +    PciExDeviceConfiguration.DeviceCtlRelaxOrder =
> + EFI_PCI_EXPRESS_NOT_APPLICABLE;  }
> +
> 
>    if (mPciExPlatformProtocol != NULL) {
>      return mPciExPlatformProtocol->NotifyDeviceState (
> --
> 2.21.0.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 06/12] PciBusDxe: New PCI Express feature No-Snoop
       [not found] ` <15F1378385E00982.18602@groups.io>
@ 2020-02-07 20:22   ` Javeed, Ashraf
  0 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:22 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch can also be viewed in the following repo:-
https://github.com/ashrafj/edk2-staging/commit/b83f0f959ba7608bd802c19f9a022fad9e5d01cc

Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Saturday, February 8, 2020 1:35 AM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 06/12]
> PciBusDxe: New PCI Express feature No-Snoop
> 
> 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 No-Snoop (NS), that
> enables the PCI function to initiate requests if it does not require hardware
> enforced cache-coherency for its transactions.
> 
> 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.
> 
> 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 | 70
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h | 18
> ++++++++++++++++++  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> |  5 ++++-  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 62
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 155 insertions(+), 1 deletion(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> index d3d795d..e610b52 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> @@ -293,6 +293,7 @@ struct _PCI_IO_DEVICE {
>    UINT8                                     SetupMPS;
>    UINT8                                     SetupMRRS;
>    PCI_FEATURE_POLICY                        SetupRO;
> +  PCI_FEATURE_POLICY                        SetupNS;
>  };
> 
>  #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 3262b76..df85366 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> @@ -451,3 +451,73 @@ ProgramRelaxOrder (
>    return Status;
>  }
> 
> +/**
> +  Overrides the PCI Device Control register No-Snoop register field; 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
> +ProgramNoSnoop (
> +  IN PCI_IO_DEVICE          *PciDevice,
> +  IN VOID                   *PciExFeatureConfiguration
> +  )
> +{
> +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> +  UINT32                      Offset;
> +  EFI_STATUS                  Status;
> +  EFI_TPL                     OldTpl;
> +
> +  PcieDev.Uint16 = 0;
> +  Offset = PciDevice->PciExpressCapabilityOffset +
> +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> + Status = PciDevice->PciIo.Pci.Read (
> +                                  &PciDevice->PciIo,
> +                                  EfiPciIoWidthUint16,
> +                                  Offset,
> +                                  1,
> +                                  &PcieDev.Uint16
> +                                  );
> +  ASSERT (Status == EFI_SUCCESS);
> +
> +  if (PciDevice->SetupNS.Override
> +      &&  PcieDev.Bits.NoSnoop != PciDevice->SetupNS.Act
> +      ) {
> +    PcieDev.Bits.NoSnoop = PciDevice->SetupNS.Act;
> +    DEBUG (( DEBUG_INFO, "NS=%d", PciDevice->SetupNS.Act));
> +
> +    //
> +    // 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,
> +                                    &PcieDev.Uint16
> +                                    );
> +    //
> +    // Restore TPL to its original level
> +    //
> +    gBS->RestoreTPL (OldTpl);
> +
> +    if (!EFI_ERROR(Status)) {
> +      PciDevice->PciExpressCapabilityStructure.DeviceControl.Uint16 =
> PcieDev.Uint16;
> +    } else {
> +      ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber,
> PciDevice->FunctionNumber, Offset);
> +    }
> +  } else {
> +    DEBUG (( DEBUG_INFO, "No NS,", PciDevice->SetupRO.Act));  }
> +
> +  return Status;
> +}
> +
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> index 0d17801..ee636ce 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> @@ -115,4 +115,22 @@ ProgramRelaxOrder (
>    IN VOID                   *PciExFeatureConfiguration
>    );
> 
> +/**
> +  Overrides the PCI Device Control register No-Snoop register field; 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
> +ProgramNoSnoop (
> +  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 267f570..d264d13 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> @@ -46,7 +46,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY
> mPciExpressPlatformPolicy = {
>      //
>      // support for PCI Express feature - No-Snoop
>      //
> -    FALSE,
> +    TRUE,
>      //
>      // support for PCI Express feature - ASPM state
>      //
> @@ -116,6 +116,9 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT
> mPciExpressFeatureInitializationList[]
>    },
>    {
>      PciExpressFeatureProgramPhase,        PciExpressRelaxOrder,
> ProgramRelaxOrder
> +  },
> +  {
> +    PciExpressFeatureProgramPhase,        PciExpressNoSnoop,
> ProgramNoSnoop
>    }
>  };
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> index 40eb8a3..954ce16 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> @@ -188,6 +188,46 @@ SetDevicePolicyPciExpressRo (
>    }
>  }
> 
> +/**
> +  Routine to set the device-specific policy for the PCI feature
> +No-Snoop enable
> +  or disable
> +
> +  @param  NoSnoop       value corresponding to data type
> EFI_PCI_EXPRESS_NO_SNOOP
> +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> +**/
> +VOID
> +SetDevicePolicyPciExpressNs (
> +  IN  EFI_PCI_EXPRESS_NO_SNOOP  NoSnoop,
> +  OUT PCI_IO_DEVICE             *PciDevice
> +  )
> +{
> +  //
> +  // implementation specific rules for the usage of PCI_FEATURE_POLICY
> +members
> +  // exclusively for the PCI Feature No-Snoop
> +  //
> +  // .Override = 0 to skip this PCI feature No-Snoop for the PCI device
> +  // .Override = 1 to program this No-Snoop PCI feature
> +  //      .Act = 1 to enable the No-Snoop in the PCI device
> +  //      .Act = 0 to disable the No-Snoop in the PCI device
> +  //
> +  switch (NoSnoop) {
> +    case  EFI_PCI_EXPRESS_NS_AUTO:
> +      PciDevice->SetupNS.Override = 0;
> +      break;
> +    case  EFI_PCI_EXPRESS_NS_DISABLE:
> +      PciDevice->SetupNS.Override = 1;
> +      PciDevice->SetupNS.Act = 0;
> +      break;
> +    case  EFI_PCI_EXPRESS_NS_ENABLE:
> +      PciDevice->SetupNS.Override = 1;
> +      PciDevice->SetupNS.Act = 1;
> +      break;
> +    default:
> +      PciDevice->SetupNS.Override = 0;
> +      break;
> +  }
> +}
> +
>  /**
>    Generic routine to setup the PCI features as per its predetermined defaults.
>  **/
> @@ -211,6 +251,8 @@ SetupDefaultPciExpressDevicePolicy (
> 
>    PciDevice->SetupRO.Override = 0;
> 
> +  PciDevice->SetupNS.Override = 0;
> +
>  }
> 
>  /**
> @@ -309,6 +351,15 @@ GetPciExpressDevicePolicy (
>        PciDevice->SetupRO.Override = 0;
>      }
> 
> +    //
> +    // set the device specific policy for No-Snoop
> +    //
> +    if (mPciExpressPlatformPolicy.NoSnoop) {
> +      SetDevicePolicyPciExpressNs (PciExpressDevicePolicy.DeviceCtlNoSnoop,
> PciDevice);
> +    } else {
> +      PciDevice->SetupNS.Override = 0;
> +    }
> +
> 
>      DEBUG ((
>        DEBUG_INFO,
> @@ -499,6 +550,17 @@ PciExpressPlatformNotifyDeviceState (
>      PciExDeviceConfiguration.DeviceCtlRelaxOrder =
> EFI_PCI_EXPRESS_NOT_APPLICABLE;
>    }
> 
> +  //
> +  // get the device-specific state for the PCIe NoSnoop feature  //  if
> + (mPciExpressPlatformPolicy.NoSnoop) {
> +    PciExDeviceConfiguration.DeviceCtlNoSnoop = PciDevice-
> >PciExpressCapabilityStructure.DeviceControl.Bits.NoSnoop
> +                                                    ? EFI_PCI_EXPRESS_NS_ENABLE
> +                                                    :
> + EFI_PCI_EXPRESS_NS_DISABLE;  } else {
> +    PciExDeviceConfiguration.DeviceCtlNoSnoop =
> + EFI_PCI_EXPRESS_NOT_APPLICABLE;  }
> +
> 
>    if (mPciExPlatformProtocol != NULL) {
>      return mPciExPlatformProtocol->NotifyDeviceState (
> --
> 2.21.0.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] PciBusDxe: New PCI Express feature Completion Timeout
       [not found] ` <15F137842EDDF11D.15938@groups.io>
@ 2020-02-07 20:24   ` Javeed, Ashraf
  0 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:24 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch can also be viewed in the following repo:-
https://github.com/ashrafj/edk2-staging/commit/7f0ea5bf87b220b8941bacac99f956948785571d

Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Saturday, February 8, 2020 1:35 AM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12]
> PciBusDxe: New PCI Express feature Completion Timeout
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2313
> 
> The code changes are made; as per the PCI Express Base Specification 4 Revision
> 1; to enable the configuration of PCI Express feature Completion Timeout (CTO),
> that enables the PCI function to wait on programmed dura- tion for its
> transactions before timeout, or disable its detection mecha- nism.
> 
> The code changes are made to configure only those PCI devices which are
> requested by platform for override through the new PCI Express Platform
> protocol interface for device-specific policies. The changes are made to also
> comply with the device-specific capability attributes.
> 
> The code follows the below implementation specific rules in case the req-
> uested platform policy does not match with the device-specific capability
> attributes:-
> (1) if device is capable of Range A only and if platform ask for any of
>     ranges B, C, D; than this implementation will only program the default
>     range value for the duration of 50us to 50ms
> (2) if device is capable of Range B, or range B & C, or Ranges B, C & D
>     only and if the platform ask for the Range A; than this implementation
>     will only program the default range value for the duration of 50us to
>     50ms
> (3) if the device is capable of Range B only, or the ranges A & B; and if
>     the platform ask for Range C, or Range D values, than this implement-
>     ation will only program the Range B value for the duration of 65ms to
>     210ms
> (4) if the device is capable of Ranges B & C, or Ranges A, B, and C; and
>     if the platform ask for Range D values; than this implementation will
>     only program the Range C for the duration of 1s to 3.5s
> 
> Signed-off-by: Ashraf Javeed <ashraf.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
> 
> 
> 


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12] PciBusDxe: New PCI Express feature AtomicOp
       [not found] ` <15F13784AAF69472.18602@groups.io>
@ 2020-02-07 20:25   ` Javeed, Ashraf
       [not found]   ` <15F1389AA432C2B6.18602@groups.io>
  1 sibling, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:25 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch can also be viewed in the following repo:-
https://github.com/ashrafj/edk2-staging/commit/6c502aea8f5483abbded1023166896c6baa9290d

Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Saturday, February 8, 2020 1:35 AM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12]
> PciBusDxe: New PCI Express feature AtomicOp
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2499
> 
> This code change handles two PCI Express features related to AtomicOp, in
> compliance with the PCI Express Base SPecification 5:
> (1) configuring PCI function as an AtomicOp Requester
> (2) Enabling of Port Egress blocking depending on AtomicOp Routing
>     Capability
> 
> These is programmed based on the following criteria:- For a PCI Bridge device:
>  - enables as AtomicOp Requester solely based on platform provided device
>    policy
>  - enabling of Port Egress blocking is based on platform device policy;
>    only if its device capability register's AtomicOp Routing bit is 1
> 
> For an PCI EndPoint (EP) device:
>  - if the platform's device policy wants to enable the AtomicOp Requester
>    function for this device, than this device is enabled if all its bridge
>    devices have the AtomicOp Routing capability bit set
>  - Enabling of Port Egress disable is not applicable to PCI EP device
> 
> For an PCI RCiEP device:
>  - the AtomicOp Requester functionality is enabled solely based on the
>    device policy provided by platform
>  - similar to PCI EP device, the enabling of port Egress blocking is not
>    applicable
> 
> 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 | 161
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h |  35
> +++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  |  23
> ++++++++++++++++++++++-
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h  |   5 +++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c |  23
> +++++++++++++++++++++++
>  6 files changed, 247 insertions(+), 1 deletion(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> index 9b03c12..57ef1b2 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> @@ -295,6 +295,7 @@ struct _PCI_IO_DEVICE {
>    PCI_FEATURE_POLICY                        SetupRO;
>    PCI_FEATURE_POLICY                        SetupNS;
>    PCI_FEATURE_POLICY                        SetupCTO;
> +  EFI_PCI_EXPRESS_ATOMIC_OP                 SetupAtomicOp;
>  };
> 
>  #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 f3f4d39..5c76ba4 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> @@ -908,3 +908,164 @@ ProgramCompletionTimeout (
>    return Status;
>  }
> 
> +/**
> +  Routine to setup the AtomicOp Requester in the PCI device, verifies
> +the routing
> +  support in the bridge devices, to be complaint as per the PCI Base
> specification.
> +
> +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> +  @param PciExFeatureConfiguration      pointer to common configuration
> table to
> +                                        initialize the PCI Express
> + feature
> +
> +  @retval EFI_SUCCESS                   bridge device routing capability is successful.
> +          EFI_INVALID_PARAMETER         input parameter is NULL
> +**/
> +EFI_STATUS
> +SetupAtomicOpRoutingSupport (
> +  IN PCI_IO_DEVICE                              *PciDevice,
> +  IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> *PciExFeatureConfiguration
> +  )
> +{
> +  //
> +  // to enable the AtomicOp Requester in the PCI EP device; its Root
> +Port (bridge),
> +  // and its PCIe switch upstream & downstream ports (if present) needs
> +to support
> +  // the AtomicOp Routing capability.
> +  //
> +  if (IS_PCI_BRIDGE (&PciDevice->Pci)) {
> +    if (!PciDevice-
> >PciExpressCapabilityStructure.DeviceCapability2.Bits.AtomicOpRouting) {
> +      //
> +      // since the AtomicOp Routing support flag is initialized as TRUE, negate
> +      // in case if any of the PCI Bridge device in the PCI tree does not support
> +      // the AtomicOp Routing capability
> +      //
> +      if (PciExFeatureConfiguration == NULL) {
> +        return EFI_INVALID_PARAMETER;
> +      }
> +      PciExFeatureConfiguration->AtomicOpRoutingSupported = FALSE;
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Overrides the PCI Device Control 2 register AtomicOp Requester enable
> +field; 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
> +ProgramAtomicOp (
> +  IN PCI_IO_DEVICE                            *PciDevice,
> +  IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciExFeatureConfiguration
> +  )
> +{
> +  PCI_REG_PCIE_DEVICE_CONTROL2  PcieDev;
> +  UINT32                        Offset;
> +  EFI_STATUS                    Status;
> +  EFI_TPL                       OldTpl;
> +
> +  PcieDev.Uint16 = 0;
> +  Offset = PciDevice->PciExpressCapabilityOffset +
> +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2);
> + Status = PciDevice->PciIo.Pci.Read (
> +                                  &PciDevice->PciIo,
> +                                  EfiPciIoWidthUint16,
> +                                  Offset,
> +                                  1,
> +                                  &PcieDev.Uint16
> +                                  );
> +  ASSERT (Status == EFI_SUCCESS);
> +
> +  if (PciDevice->SetupAtomicOp.Override) {
> +    //
> +    // override AtomicOp requester device control bit of the device based on the
> +    // platform request
> +    //
> +    if (IS_PCI_BRIDGE (&PciDevice->Pci)) {
> +      //
> +      // for a bridge device as AtomicOp Requester function; only platform
> override
> +      // request is used to set the device control register
> +      //
> +      if (PcieDev.Bits.AtomicOpRequester != PciDevice-
> >SetupAtomicOp.Enable_AtomicOpRequester) {
> +        PcieDev.Bits.AtomicOpRequester = PciDevice-
> >SetupAtomicOp.Enable_AtomicOpRequester;
> +      }
> +      //
> +      // if platform also request its AtomicOp Egress blocking to be enabled; set
> +      // only if its device capability's AtomicOpRouting bit is 1.
> +      // applicable to only the bridge devices
> +      //
> +      if (PciDevice->SetupAtomicOp.Enable_AtomicOpEgressBlocking) {
> +        if (PciDevice-
> >PciExpressCapabilityStructure.DeviceCapability2.Bits.AtomicOpRouting) {
> +          PcieDev.Bits.AtomicOpEgressBlocking = 1;
> +        }
> +      }
> +    } else {
> +      //
> +      // in the case of non-bridge device
> +      //
> +      if (PciExFeatureConfiguration) {
> +        //
> +        // for a device as AtomicOp Requester function; its bridge devices should
> +        // support the AtomicOp Routing capability to enable the device's as a
> +        // requester function
> +        //
> +        if (PciExFeatureConfiguration->AtomicOpRoutingSupported) {
> +          if (PcieDev.Bits.AtomicOpRequester != PciDevice-
> >SetupAtomicOp.Enable_AtomicOpRequester) {
> +            PcieDev.Bits.AtomicOpRequester = PciDevice-
> >SetupAtomicOp.Enable_AtomicOpRequester;
> +          }
> +        }
> +      } else {
> +        //
> +        // for the RCiEP device or the bridge device without any child, setup
> AtomicOp
> +        // Requester as per platform's device policy
> +        //
> +        if (PcieDev.Bits.AtomicOpRequester != PciDevice-
> >SetupAtomicOp.Enable_AtomicOpRequester) {
> +          PcieDev.Bits.AtomicOpRequester = PciDevice-
> >SetupAtomicOp.Enable_AtomicOpRequester;
> +        }
> +      }
> +      //
> +      // the enabling of AtomicOp Egress Blocking is not applicable to a non-
> bridge
> +      // device
> +      //
> +    }
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "AtomicOp=%d,",
> +      PcieDev.Bits.AtomicOpRequester
> +      ));
> +
> +    //
> +    // 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,
> +                                    &PcieDev.Uint16
> +                                    );
> +    //
> +    // Restore TPL to its original level
> +    //
> +    gBS->RestoreTPL (OldTpl);
> +
> +    if (!EFI_ERROR(Status)) {
> +      PciDevice->PciExpressCapabilityStructure.DeviceControl2.Uint16 =
> PcieDev.Uint16;
> +    } else {
> +      ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber,
> PciDevice->FunctionNumber, Offset);
> +    }
> +  } else {
> +    DEBUG (( DEBUG_INFO, "No AtomicOp,"));  }
> +
> +  return Status;
> +}
> +
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> index 2ee7d4d..1e287fc 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> @@ -168,4 +168,39 @@ ProgramCompletionTimeout (
>    IN VOID                   *PciExFeatureConfiguration
>    );
> 
> +/**
> +  Routine to setup the AtomicOp Requester in the PCI device, verifies
> +the routing
> +  support in the bridge devices, to be complaint as per the PCI Base
> specification.
> +
> +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> +  @param PciExFeatureConfiguration      pointer to common configuration
> table to
> +                                        initialize the PCI Express
> + feature
> +
> +  @retval EFI_SUCCESS                   bridge device routing capability is successful.
> +          EFI_INVALID_PARAMETER         input parameter is NULL
> +**/
> +EFI_STATUS
> +SetupAtomicOpRoutingSupport (
> +  IN PCI_IO_DEVICE                              *PciDevice,
> +  IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> *PciExFeatureConfiguration
> +  );
> +
> +/**
> +  Overrides the PCI Device Control 2 register AtomicOp Requester enable
> +field; 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
> +ProgramAtomicOp (
> +  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 d4459f3..9d624a0 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> @@ -62,7 +62,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY
> mPciExpressPlatformPolicy = {
>      //
>      // support for PCI Express feature - Atomic Op
>      //
> -    FALSE,
> +    TRUE,
>      //
>      // support for PCI Express feature - LTR
>      //
> @@ -125,6 +125,12 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT
> mPciExpressFeatureInitializationList[]
>    },
>    {
>      PciExpressFeatureProgramPhase,        PciExpressCto,
> ProgramCompletionTimeout
> +  },
> +  {
> +    PciExpressFeatureSetupPhase,          PciExpressAtomicOp,
> SetupAtomicOpRoutingSupport
> +  },
> +  {
> +    PciExpressFeatureProgramPhase,        PciExpressAtomicOp,
> ProgramAtomicOp
>    }
>  };
> 
> @@ -297,6 +303,16 @@ IsPciExpressFeatureExtendedSetupRequired (
>          &&
> PciExpressPolicy[mPciExpressFeatureInitializationList[idx].PciExpressFeatureId]
> == TRUE
>      ) {
>        return TRUE;
> +    } else if (
> +        //
> +        // the PCI Express feature does not require extended setup phase but it
> +        // does require global flag to track the AtomicOpRouting caoability to
> +        // be tracked for all its bridge devices
> +        //
> +        idx == PciExpressAtomicOp
> +        && PciExpressPolicy[idx] == TRUE
> +        ) {
> +      return TRUE;
>      }
>    }
> 
> @@ -637,6 +653,11 @@ CreatePciRootBridgeDeviceNode (
>      // the devices in the PCI tree
>      //
>      PciConfigTable->Lock_Max_Read_Request_Size  = FALSE;
> +    //
> +    // start by assuming the AtomicOp Routing capability is supported in the PCI
> +    // tree
> +    //
> +    PciConfigTable->AtomicOpRoutingSupported    = TRUE;
>    }
> 
>    RootBridgeNode->PciExFeaturesConfigurationTable  = PciConfigTable; diff --
> git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> index a1fc39c..2bd565e 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> @@ -80,6 +80,11 @@ struct
> _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE {
>    // lock the Max_Read_Request_Size for the entire PCI tree of a root port
>    //
>    BOOLEAN                                   Lock_Max_Read_Request_Size;
> +  //
> +  // to record the AtomicOp Routing capability of the PCI Heirarchy to
> + enable  // the AtomicOp of the EP device  //
> +  BOOLEAN                                   AtomicOpRoutingSupported;
>  };
> 
>  //
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> index 1afea19..2707976 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> @@ -334,6 +334,8 @@ SetupDefaultPciExpressDevicePolicy (
> 
>    PciDevice->SetupCTO.Override = 0;
> 
> +  PciDevice->SetupAtomicOp.Override = 0;
> +
>  }
> 
>  /**
> @@ -450,6 +452,14 @@ GetPciExpressDevicePolicy (
>        PciDevice->SetupCTO.Override = 0;
>      }
> 
> +    //
> +    // set the device-specific policy for AtomicOp
> +    //
> +    if (mPciExpressPlatformPolicy.AtomicOp) {
> +      PciDevice->SetupAtomicOp = PciExpressDevicePolicy.DeviceCtl2AtomicOp;
> +    } else {
> +      PciDevice->SetupAtomicOp.Override = 0;
> +    }
> 
>      DEBUG ((
>        DEBUG_INFO,
> @@ -692,6 +702,19 @@ PciExpressPlatformNotifyDeviceState (
>      PciExDeviceConfiguration.CTOsupport = EFI_PCI_EXPRESS_NOT_APPLICABLE;
>    }
> 
> +  //
> +  // get the device-specific state for the PCIe AtomicOp feature  //
> + if (mPciExpressPlatformPolicy.AtomicOp) {
> +    PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpRequester
> +    = (UINT8)PciDevice-
> >PciExpressCapabilityStructure.DeviceControl2.Bits.AtomicOpRequester;
> +
> PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpEgressBlockin
> g
> +    =
> + (UINT8)PciDevice->PciExpressCapabilityStructure.DeviceControl2.Bits.At
> + omicOpEgressBlocking;
> +  } else {
> +    PciExDeviceConfiguration.DeviceCtl2AtomicOp.Override = 0;
> +    PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpRequester
> = 0;
> +
> + PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpEgressBlock
> + ing = 0;  }
> 
>    if (mPciExPlatformProtocol != NULL) {
>      return mPciExPlatformProtocol->NotifyDeviceState (
> --
> 2.21.0.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12] PciBusDxe: New PCI Express feature AtomicOp
       [not found]   ` <15F1389AA432C2B6.18602@groups.io>
@ 2020-02-07 20:27     ` Javeed, Ashraf
  0 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:27 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

Link correction made below.

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Saturday, February 8, 2020 1:56 AM
> To: devel@edk2.groups.io; Javeed, Ashraf <ashraf.javeed@intel.com>
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12]
> PciBusDxe: New PCI Express feature AtomicOp
> 
> This patch can also be viewed in the following repo:-
https://github.com/ashrafj/edk2-staging/commit/176fccc85714fbbae616821ba355cd4306cecb87
> 
> Thanks
> Ashraf
> 
> > -----Original Message-----
> > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> > Ashraf
> > Sent: Saturday, February 8, 2020 1:35 AM
> > To: devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > <hao.a.wu@intel.com>; Ni, Ray <ray.ni@intel.com>
> > Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12]
> > PciBusDxe: New PCI Express feature AtomicOp
> >
> > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2499
> >
> > This code change handles two PCI Express features related to AtomicOp,
> > in compliance with the PCI Express Base SPecification 5:
> > (1) configuring PCI function as an AtomicOp Requester
> > (2) Enabling of Port Egress blocking depending on AtomicOp Routing
> >     Capability
> >
> > These is programmed based on the following criteria:- For a PCI Bridge device:
> >  - enables as AtomicOp Requester solely based on platform provided device
> >    policy
> >  - enabling of Port Egress blocking is based on platform device policy;
> >    only if its device capability register's AtomicOp Routing bit is 1
> >
> > For an PCI EndPoint (EP) device:
> >  - if the platform's device policy wants to enable the AtomicOp Requester
> >    function for this device, than this device is enabled if all its bridge
> >    devices have the AtomicOp Routing capability bit set
> >  - Enabling of Port Egress disable is not applicable to PCI EP device
> >
> > For an PCI RCiEP device:
> >  - the AtomicOp Requester functionality is enabled solely based on the
> >    device policy provided by platform
> >  - similar to PCI EP device, the enabling of port Egress blocking is not
> >    applicable
> >
> > 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 | 161
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > +++++++++++++++++++++++++++++++
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h |  35
> > +++++++++++++++++++++++++++++++++++
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  |  23
> > ++++++++++++++++++++++-
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h  |   5 +++++
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c |  23
> > +++++++++++++++++++++++
> >  6 files changed, 247 insertions(+), 1 deletion(-)
> >
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > index 9b03c12..57ef1b2 100644
> > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > @@ -295,6 +295,7 @@ struct _PCI_IO_DEVICE {
> >    PCI_FEATURE_POLICY                        SetupRO;
> >    PCI_FEATURE_POLICY                        SetupNS;
> >    PCI_FEATURE_POLICY                        SetupCTO;
> > +  EFI_PCI_EXPRESS_ATOMIC_OP                 SetupAtomicOp;
> >  };
> >
> >  #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 f3f4d39..5c76ba4 100644
> > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> > @@ -908,3 +908,164 @@ ProgramCompletionTimeout (
> >    return Status;
> >  }
> >
> > +/**
> > +  Routine to setup the AtomicOp Requester in the PCI device, verifies
> > +the routing
> > +  support in the bridge devices, to be complaint as per the PCI Base
> > specification.
> > +
> > +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> > +  @param PciExFeatureConfiguration      pointer to common configuration
> > table to
> > +                                        initialize the PCI Express
> > + feature
> > +
> > +  @retval EFI_SUCCESS                   bridge device routing capability is
> successful.
> > +          EFI_INVALID_PARAMETER         input parameter is NULL
> > +**/
> > +EFI_STATUS
> > +SetupAtomicOpRoutingSupport (
> > +  IN PCI_IO_DEVICE                              *PciDevice,
> > +  IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> > *PciExFeatureConfiguration
> > +  )
> > +{
> > +  //
> > +  // to enable the AtomicOp Requester in the PCI EP device; its Root
> > +Port (bridge),
> > +  // and its PCIe switch upstream & downstream ports (if present)
> > +needs to support
> > +  // the AtomicOp Routing capability.
> > +  //
> > +  if (IS_PCI_BRIDGE (&PciDevice->Pci)) {
> > +    if (!PciDevice-
> > >PciExpressCapabilityStructure.DeviceCapability2.Bits.AtomicOpRouting)
> > >{
> > +      //
> > +      // since the AtomicOp Routing support flag is initialized as TRUE, negate
> > +      // in case if any of the PCI Bridge device in the PCI tree does not support
> > +      // the AtomicOp Routing capability
> > +      //
> > +      if (PciExFeatureConfiguration == NULL) {
> > +        return EFI_INVALID_PARAMETER;
> > +      }
> > +      PciExFeatureConfiguration->AtomicOpRoutingSupported = FALSE;
> > +    }
> > +  }
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > +  Overrides the PCI Device Control 2 register AtomicOp Requester
> > +enable field; 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
> > +ProgramAtomicOp (
> > +  IN PCI_IO_DEVICE                            *PciDevice,
> > +  IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> > +*PciExFeatureConfiguration
> > +  )
> > +{
> > +  PCI_REG_PCIE_DEVICE_CONTROL2  PcieDev;
> > +  UINT32                        Offset;
> > +  EFI_STATUS                    Status;
> > +  EFI_TPL                       OldTpl;
> > +
> > +  PcieDev.Uint16 = 0;
> > +  Offset = PciDevice->PciExpressCapabilityOffset +
> > +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2);
> > + Status = PciDevice->PciIo.Pci.Read (
> > +                                  &PciDevice->PciIo,
> > +                                  EfiPciIoWidthUint16,
> > +                                  Offset,
> > +                                  1,
> > +                                  &PcieDev.Uint16
> > +                                  );
> > +  ASSERT (Status == EFI_SUCCESS);
> > +
> > +  if (PciDevice->SetupAtomicOp.Override) {
> > +    //
> > +    // override AtomicOp requester device control bit of the device based on
> the
> > +    // platform request
> > +    //
> > +    if (IS_PCI_BRIDGE (&PciDevice->Pci)) {
> > +      //
> > +      // for a bridge device as AtomicOp Requester function; only
> > + platform
> > override
> > +      // request is used to set the device control register
> > +      //
> > +      if (PcieDev.Bits.AtomicOpRequester != PciDevice-
> > >SetupAtomicOp.Enable_AtomicOpRequester) {
> > +        PcieDev.Bits.AtomicOpRequester = PciDevice-
> > >SetupAtomicOp.Enable_AtomicOpRequester;
> > +      }
> > +      //
> > +      // if platform also request its AtomicOp Egress blocking to be enabled; set
> > +      // only if its device capability's AtomicOpRouting bit is 1.
> > +      // applicable to only the bridge devices
> > +      //
> > +      if (PciDevice->SetupAtomicOp.Enable_AtomicOpEgressBlocking) {
> > +        if (PciDevice-
> > >PciExpressCapabilityStructure.DeviceCapability2.Bits.AtomicOpRouting)
> > >{
> > +          PcieDev.Bits.AtomicOpEgressBlocking = 1;
> > +        }
> > +      }
> > +    } else {
> > +      //
> > +      // in the case of non-bridge device
> > +      //
> > +      if (PciExFeatureConfiguration) {
> > +        //
> > +        // for a device as AtomicOp Requester function; its bridge devices should
> > +        // support the AtomicOp Routing capability to enable the device's as a
> > +        // requester function
> > +        //
> > +        if (PciExFeatureConfiguration->AtomicOpRoutingSupported) {
> > +          if (PcieDev.Bits.AtomicOpRequester != PciDevice-
> > >SetupAtomicOp.Enable_AtomicOpRequester) {
> > +            PcieDev.Bits.AtomicOpRequester = PciDevice-
> > >SetupAtomicOp.Enable_AtomicOpRequester;
> > +          }
> > +        }
> > +      } else {
> > +        //
> > +        // for the RCiEP device or the bridge device without any
> > + child, setup
> > AtomicOp
> > +        // Requester as per platform's device policy
> > +        //
> > +        if (PcieDev.Bits.AtomicOpRequester != PciDevice-
> > >SetupAtomicOp.Enable_AtomicOpRequester) {
> > +          PcieDev.Bits.AtomicOpRequester = PciDevice-
> > >SetupAtomicOp.Enable_AtomicOpRequester;
> > +        }
> > +      }
> > +      //
> > +      // the enabling of AtomicOp Egress Blocking is not applicable
> > + to a non-
> > bridge
> > +      // device
> > +      //
> > +    }
> > +    DEBUG ((
> > +      DEBUG_INFO,
> > +      "AtomicOp=%d,",
> > +      PcieDev.Bits.AtomicOpRequester
> > +      ));
> > +
> > +    //
> > +    // 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,
> > +                                    &PcieDev.Uint16
> > +                                    );
> > +    //
> > +    // Restore TPL to its original level
> > +    //
> > +    gBS->RestoreTPL (OldTpl);
> > +
> > +    if (!EFI_ERROR(Status)) {
> > +      PciDevice->PciExpressCapabilityStructure.DeviceControl2.Uint16
> > + =
> > PcieDev.Uint16;
> > +    } else {
> > +      ReportPciWriteError (PciDevice->BusNumber,
> > + PciDevice->DeviceNumber,
> > PciDevice->FunctionNumber, Offset);
> > +    }
> > +  } else {
> > +    DEBUG (( DEBUG_INFO, "No AtomicOp,"));  }
> > +
> > +  return Status;
> > +}
> > +
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> > index 2ee7d4d..1e287fc 100644
> > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> > @@ -168,4 +168,39 @@ ProgramCompletionTimeout (
> >    IN VOID                   *PciExFeatureConfiguration
> >    );
> >
> > +/**
> > +  Routine to setup the AtomicOp Requester in the PCI device, verifies
> > +the routing
> > +  support in the bridge devices, to be complaint as per the PCI Base
> > specification.
> > +
> > +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> > +  @param PciExFeatureConfiguration      pointer to common configuration
> > table to
> > +                                        initialize the PCI Express
> > + feature
> > +
> > +  @retval EFI_SUCCESS                   bridge device routing capability is
> successful.
> > +          EFI_INVALID_PARAMETER         input parameter is NULL
> > +**/
> > +EFI_STATUS
> > +SetupAtomicOpRoutingSupport (
> > +  IN PCI_IO_DEVICE                              *PciDevice,
> > +  IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> > *PciExFeatureConfiguration
> > +  );
> > +
> > +/**
> > +  Overrides the PCI Device Control 2 register AtomicOp Requester
> > +enable field; 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
> > +ProgramAtomicOp (
> > +  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 d4459f3..9d624a0 100644
> > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > @@ -62,7 +62,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY
> > mPciExpressPlatformPolicy = {
> >      //
> >      // support for PCI Express feature - Atomic Op
> >      //
> > -    FALSE,
> > +    TRUE,
> >      //
> >      // support for PCI Express feature - LTR
> >      //
> > @@ -125,6 +125,12 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT
> > mPciExpressFeatureInitializationList[]
> >    },
> >    {
> >      PciExpressFeatureProgramPhase,        PciExpressCto,
> > ProgramCompletionTimeout
> > +  },
> > +  {
> > +    PciExpressFeatureSetupPhase,          PciExpressAtomicOp,
> > SetupAtomicOpRoutingSupport
> > +  },
> > +  {
> > +    PciExpressFeatureProgramPhase,        PciExpressAtomicOp,
> > ProgramAtomicOp
> >    }
> >  };
> >
> > @@ -297,6 +303,16 @@ IsPciExpressFeatureExtendedSetupRequired (
> >          &&
> > PciExpressPolicy[mPciExpressFeatureInitializationList[idx].PciExpressF
> > eatureId]
> > == TRUE
> >      ) {
> >        return TRUE;
> > +    } else if (
> > +        //
> > +        // the PCI Express feature does not require extended setup phase but it
> > +        // does require global flag to track the AtomicOpRouting caoability to
> > +        // be tracked for all its bridge devices
> > +        //
> > +        idx == PciExpressAtomicOp
> > +        && PciExpressPolicy[idx] == TRUE
> > +        ) {
> > +      return TRUE;
> >      }
> >    }
> >
> > @@ -637,6 +653,11 @@ CreatePciRootBridgeDeviceNode (
> >      // the devices in the PCI tree
> >      //
> >      PciConfigTable->Lock_Max_Read_Request_Size  = FALSE;
> > +    //
> > +    // start by assuming the AtomicOp Routing capability is supported in the
> PCI
> > +    // tree
> > +    //
> > +    PciConfigTable->AtomicOpRoutingSupported    = TRUE;
> >    }
> >
> >    RootBridgeNode->PciExFeaturesConfigurationTable  = PciConfigTable;
> > diff -- git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > index a1fc39c..2bd565e 100644
> > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > @@ -80,6 +80,11 @@ struct
> > _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE {
> >    // lock the Max_Read_Request_Size for the entire PCI tree of a root port
> >    //
> >    BOOLEAN                                   Lock_Max_Read_Request_Size;
> > +  //
> > +  // to record the AtomicOp Routing capability of the PCI Heirarchy
> > + to enable  // the AtomicOp of the EP device  //
> > +  BOOLEAN                                   AtomicOpRoutingSupported;
> >  };
> >
> >  //
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > index 1afea19..2707976 100644
> > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > @@ -334,6 +334,8 @@ SetupDefaultPciExpressDevicePolicy (
> >
> >    PciDevice->SetupCTO.Override = 0;
> >
> > +  PciDevice->SetupAtomicOp.Override = 0;
> > +
> >  }
> >
> >  /**
> > @@ -450,6 +452,14 @@ GetPciExpressDevicePolicy (
> >        PciDevice->SetupCTO.Override = 0;
> >      }
> >
> > +    //
> > +    // set the device-specific policy for AtomicOp
> > +    //
> > +    if (mPciExpressPlatformPolicy.AtomicOp) {
> > +      PciDevice->SetupAtomicOp =
> PciExpressDevicePolicy.DeviceCtl2AtomicOp;
> > +    } else {
> > +      PciDevice->SetupAtomicOp.Override = 0;
> > +    }
> >
> >      DEBUG ((
> >        DEBUG_INFO,
> > @@ -692,6 +702,19 @@ PciExpressPlatformNotifyDeviceState (
> >      PciExDeviceConfiguration.CTOsupport =
> EFI_PCI_EXPRESS_NOT_APPLICABLE;
> >    }
> >
> > +  //
> > +  // get the device-specific state for the PCIe AtomicOp feature  //
> > + if (mPciExpressPlatformPolicy.AtomicOp) {
> > +
> PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpRequester
> > +    = (UINT8)PciDevice-
> > >PciExpressCapabilityStructure.DeviceControl2.Bits.AtomicOpRequester;
> > +
> > PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpEgressBlock
> > in
> > g
> > +    =
> > + (UINT8)PciDevice->PciExpressCapabilityStructure.DeviceControl2.Bits.
> > + At
> > + omicOpEgressBlocking;
> > +  } else {
> > +    PciExDeviceConfiguration.DeviceCtl2AtomicOp.Override = 0;
> > +
> > + PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpRequester
> > = 0;
> > +
> > + PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpEgressBlo
> > + ck
> > + ing = 0;  }
> >
> >    if (mPciExPlatformProtocol != NULL) {
> >      return mPciExPlatformProtocol->NotifyDeviceState (
> > --
> > 2.21.0.windows.1
> >
> >
> >
> 
> 
> 


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 09/12] PciBusDxe: New PCI Express feature LTR
       [not found] ` <15F13785436D3273.18602@groups.io>
@ 2020-02-07 20:28   ` Javeed, Ashraf
  0 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:28 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch can also be viewed in the following repo:-
https://github.com/ashrafj/edk2-staging/commit/fd03852add274895880971e38f07e30d5fd79863

Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Saturday, February 8, 2020 1:35 AM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 09/12]
> PciBusDxe: New PCI Express feature LTR
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2499
> 
> This code change enables the PCI Express feature LTR, in compliance with the
> PCI Express Base Specification 5, as well as in accordance its device policy, as
> follows:
> (1) all the devices capability register needs to indicate that LTR mecha-
>     nism is supported. ANy device not capable shall lead to all devices
>     state in LTR disable
> (2) if device policy of any device requests LTR mechanism enabled, than
>     based on above condition (1) is TRUE, all of the devices from root
>     bridge are enabled.
> (3) Even in case of RCiEP device without any root bridge device; if device
>     policy requests LTR enabled and device capability does not support LTR
>     shall enforce the default LTR disabled state for that device
> 
> This programming of LTR, gets the device-specific platform policy using the new
> PCI Express Platform Protocol interface (ECR version 0.8), defined in the below
> feature request:-
>   https://bugzilla.tianocore.org/show_bug.cgi?id=1954
> 
> 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 | 171
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h |  40
> ++++++++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  |  19
> ++++++++++++++++++-
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h  |   9 +++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c |  53
> +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  6 files changed, 292 insertions(+), 1 deletion(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> index 57ef1b2..7e43a26 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> @@ -296,6 +296,7 @@ struct _PCI_IO_DEVICE {
>    PCI_FEATURE_POLICY                        SetupNS;
>    PCI_FEATURE_POLICY                        SetupCTO;
>    EFI_PCI_EXPRESS_ATOMIC_OP                 SetupAtomicOp;
> +  BOOLEAN                                   SetupLtr;
>  };
> 
>  #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 5c76ba4..63a243b 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> @@ -1069,3 +1069,174 @@ ProgramAtomicOp (
>    return Status;
>  }
> 
> +/**
> +  The main routine which process the PCI feature LTR enable/disable as
> +per the
> +  device-specific platform policy, as well as in complaince with the
> +PCI Express
> +  Base specification Revision 5.
> +
> +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> +  @param PciExpressConfigurationTable  pointer to
> + PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +
> +  @retval EFI_SUCCESS                   setup of PCI feature LTR is successful.
> +**/
> +EFI_STATUS
> +SetupLtr (
> +  IN  PCI_IO_DEVICE                             *PciDevice,
> +  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciExpressConfigurationTable
> +  )
> +{
> +  PCI_REG_PCIE_DEVICE_CAPABILITY2 DeviceCap2;
> +  //
> +  // as per the PCI-Express Base Specification, in order to enable LTR
> +mechanism
> +  // in the upstream ports, all the upstream ports and its downstream
> +ports has
> +  // to support the LTR mechanism reported in its Device Capability 2
> +register
> +  //
> +  DeviceCap2.Uint32 =
> +PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Uint32;
> +
> +  if (PciExpressConfigurationTable) {
> +    //
> +    // in this phase establish 2 requirements:
> +    // (1) all the PCI devices in the hierarchy supports the LTR mechanism
> +    // (2) check and record any device-specific platform policy that wants to
> +    //     enable the LTR mechanism
> +    //
> +    if
> + (!PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Bits.LtrM
> + echanism) {
> +
> +      //
> +      // it starts with the assumption that all the PCI devices support LTR
> mechanism
> +      // and negates the flag if any PCI device Device Capability 2 register
> advertizes
> +      // as not supported
> +      //
> +      PciExpressConfigurationTable->LtrSupported = FALSE;
> +    }
> +
> +    if (PciDevice->SetupLtr == TRUE) {
> +      //
> +      // it starts with the assumption that device-specific platform policy would
> +      // be set to LTR disable, and negates the flag if any PCI device platform
> +      // policy wants to override to enable the LTR mechanism
> +      //
> +      PciExpressConfigurationTable->LtrEnable = TRUE;
> +    }
> +  } else {
> +    //
> +    // in case of RCiEP device or the bridge device with out any child device,
> +    // overrule the device policy if the device in not capable
> +    //
> +    if (!PciDevice-
> >PciExpressCapabilityStructure.DeviceCapability2.Bits.LtrMechanism
> +        && PciDevice->SetupLtr == TRUE) {
> +      PciDevice->SetupLtr = FALSE;
> +    }
> +    //
> +    // for any bridge device which is Hot-Plug capable, it is expected that
> platform
> +    // will not enforce the enabling of LTR mechanism only for the bridge device
> +    //
> +  }
> +
> +  DEBUG (( DEBUG_INFO, "LTR En: %d (LTR Cap: %d),",
> +    PciDevice->SetupLtr ? 1 : 0,
> +    PciDevice-
> >PciExpressCapabilityStructure.DeviceCapability2.Bits.LtrMechanism
> +    ));
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +ReSetupLtr (
> +  IN  PCI_IO_DEVICE                             *PciDevice,
> +  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciExpressConfigurationTable
> +  )
> +{
> +  //
> +  // not applicable to RCiEP device...
> +  // for the bridge device without any child device, the policy is
> +already overruled
> +  // based on capability in the above routine
> +  //
> +  if (PciExpressConfigurationTable) {
> +    //
> +    // in this phase align the device policy to enable LTR policy of any PCI device
> +    // in the tree if all the devices are capable to support the LTR mechanism
> +    //
> +    if (PciExpressConfigurationTable->LtrSupported == TRUE
> +        && PciExpressConfigurationTable->LtrEnable == TRUE
> +    ) {
> +      PciDevice->SetupLtr = TRUE;
> +    } else {
> +      PciDevice->SetupLtr = FALSE;
> +    }
> +  }
> +
> +  DEBUG (( DEBUG_INFO, "LTR En: %d (LTR Cap: %d),",
> +    PciDevice->SetupLtr ? 1 : 0,
> +    PciDevice-
> >PciExpressCapabilityStructure.DeviceCapability2.Bits.LtrMechanism
> +    ));
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Program the PCI Device Control 2 register LTR mechanism field; 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
> +ProgramLtr (
> +  IN PCI_IO_DEVICE          *PciDevice,
> +  IN VOID                   *PciExFeatureConfiguration
> +  )
> +{
> +  PCI_REG_PCIE_DEVICE_CONTROL2  PcieDev;
> +  UINT32                        Offset;
> +  EFI_STATUS                    Status;
> +  EFI_TPL                       OldTpl;
> +
> +  PcieDev.Uint16 = 0;
> +  Offset = PciDevice->PciExpressCapabilityOffset +
> +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2);
> + Status = PciDevice->PciIo.Pci.Read (
> +                                  &PciDevice->PciIo,
> +                                  EfiPciIoWidthUint16,
> +                                  Offset,
> +                                  1,
> +                                  &PcieDev.Uint16
> +                                  );
> +  ASSERT (Status == EFI_SUCCESS);
> +
> +  if (PciDevice->SetupLtr != (BOOLEAN) PcieDev.Bits.LtrMechanism) {
> +    PcieDev.Bits.LtrMechanism = PciDevice->SetupLtr ? 1 : 0;
> +    DEBUG (( DEBUG_INFO, "LTR=%d,", PcieDev.Bits.LtrMechanism));
> +
> +    //
> +    // 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,
> +                                    &PcieDev.Uint16
> +                                    );
> +    //
> +    // Restore TPL to its original level
> +    //
> +    gBS->RestoreTPL (OldTpl);
> +
> +    if (!EFI_ERROR(Status)) {
> +      PciDevice->PciExpressCapabilityStructure.DeviceControl2.Uint16 =
> PcieDev.Uint16;
> +    } else {
> +      ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber,
> PciDevice->FunctionNumber, Offset);
> +    }
> +  } else {
> +    DEBUG (( DEBUG_INFO, "no LTR,"));
> +  }
> +
> +  return Status;
> +}
> +
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> index 1e287fc..374fe49 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> @@ -203,4 +203,44 @@ ProgramAtomicOp (
>    IN VOID                   *PciExFeatureConfiguration
>    );
> 
> +/**
> +  The main routine which process the PCI feature LTR enable/disable as
> +per the
> +  device-specific platform policy, as well as in complaince with the
> +PCI Express
> +  Base specification Revision 5.
> +
> +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> +  @param PciFeaturesConfigurationTable  pointer to
> + PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +
> +  @retval EFI_SUCCESS                   setup of PCI feature LTR is successful.
> +**/
> +EFI_STATUS
> +SetupLtr (
> +  IN  PCI_IO_DEVICE                             *PciDevice,
> +  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciFeaturesConfigurationTable
> +  );
> +
> +EFI_STATUS
> +ReSetupLtr (
> +  IN  PCI_IO_DEVICE                             *PciDevice,
> +  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciFeaturesConfigurationTable
> +  );
> +
> +/**
> +  Program the PCI Device Control 2 register LTR mechanism field; 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
> +ProgramLtr (
> +  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 9d624a0..bdeb0d2 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> @@ -66,7 +66,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY
> mPciExpressPlatformPolicy = {
>      //
>      // support for PCI Express feature - LTR
>      //
> -    FALSE,
> +    TRUE,
>      //
>      // support for PCI Express feature - PTM
>      //
> @@ -131,6 +131,15 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT
> mPciExpressFeatureInitializationList[]
>    },
>    {
>      PciExpressFeatureProgramPhase,        PciExpressAtomicOp,
> ProgramAtomicOp
> +  },
> +  {
> +    PciExpressFeatureSetupPhase,          PciExpressLtr,        SetupLtr
> +  },
> +  {
> +    PciExpressFeatureEntendedSetupPhase,  PciExpressLtr,        ReSetupLtr
> +  },
> +  {
> +    PciExpressFeatureProgramPhase,        PciExpressLtr,        ProgramLtr
>    }
>  };
> 
> @@ -654,6 +663,14 @@ CreatePciRootBridgeDeviceNode (
>      //
>      PciConfigTable->Lock_Max_Read_Request_Size  = FALSE;
>      //
> +    // start by assuming the LTR mechanism is supported in a PCI tree
> +    //
> +    PciConfigTable->LtrSupported                = TRUE;
> +    //
> +    // the default LTR mechanism is disabled as per the PCI Base specification
> +    //
> +    PciConfigTable->LtrEnable                   = FALSE;
> +    //
>      // start by assuming the AtomicOp Routing capability is supported in the PCI
>      // tree
>      //
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> index 2bd565e..5dded7c 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> @@ -81,6 +81,15 @@ struct
> _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE {
>    //
>    BOOLEAN                                   Lock_Max_Read_Request_Size;
>    //
> +  // to record the adversity in LTR mechanism support capability among
> + the PCI  // device of an heirarchy  //
> +  BOOLEAN                                   LtrSupported;
> +  //
> +  // to enable the LTR mechansim for the entire PCI tree from a root
> + port  //
> +  BOOLEAN                                   LtrEnable;
> +  //
>    // to record the AtomicOp Routing capability of the PCI Heirarchy to enable
>    // the AtomicOp of the EP device
>    //
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> index 2707976..83b3aa7 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> @@ -307,6 +307,36 @@ SetDevicePolicyPciExpressCto (
>    }
>  }
> 
> +/**
> +  Routine to set the device-specific policy for the PCI feature LTR
> +enable/disable
> +
> +  @param  AtomicOp      value corresponding to data type
> EFI_PCI_EXPRESS_ATOMIC_OP
> +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> +
> +**/
> +VOID
> +SetDevicePolicyPciExpressLtr (
> +  IN  EFI_PCI_EXPRESS_LTR            Ltr,
> +  OUT PCI_IO_DEVICE               *PciDevice
> +  )
> +{
> +  switch (Ltr){
> +    case EFI_PCI_EXPRESS_LTR_AUTO:
> +    case EFI_PCI_EXPRESS_LTR_DISABLE:
> +      //
> +      // leave the LTR mechanism disable or restore to its default state
> +      //
> +      PciDevice->SetupLtr = FALSE;
> +      break;
> +    case EFI_PCI_EXPRESS_LTR_ENABLE:
> +      //
> +      // LTR mechanism enable
> +      //
> +      PciDevice->SetupLtr = TRUE;
> +      break;
> +  }
> +}
> +
>  /**
>    Generic routine to setup the PCI features as per its predetermined defaults.
>  **/
> @@ -336,6 +366,8 @@ SetupDefaultPciExpressDevicePolicy (
> 
>    PciDevice->SetupAtomicOp.Override = 0;
> 
> +  PciDevice->SetupLtr = FALSE;
> +
>  }
> 
>  /**
> @@ -461,6 +493,16 @@ GetPciExpressDevicePolicy (
>        PciDevice->SetupAtomicOp.Override = 0;
>      }
> 
> +    //
> +    // set the device-specific policy for LTR mechanism in the function
> +    //
> +    if (mPciExpressPlatformPolicy.Ltr) {
> +      SetDevicePolicyPciExpressLtr (PciExpressDevicePolicy.DeviceCtl2LTR,
> PciDevice);
> +    } else {
> +      PciDevice->SetupLtr = FALSE;
> +    }
> +
> +
>      DEBUG ((
>        DEBUG_INFO,
>        "[device policy: platform]"
> @@ -715,6 +757,17 @@ PciExpressPlatformNotifyDeviceState (
>      PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpRequester =
> 0;
> 
> PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpEgressBlockin
> g = 0;
>    }
> +  //
> +  // get the device-specific state for LTR mechanism in the function
> + //  if (mPciExpressPlatformPolicy.Ltr) {
> +    PciExDeviceConfiguration.DeviceCtl2LTR = PciDevice-
> >PciExpressCapabilityStructure.DeviceControl2.Bits.LtrMechanism
> +                                                ? EFI_PCI_EXPRESS_LTR_ENABLE
> +                                                :
> + EFI_PCI_EXPRESS_LTR_DISABLE;  } else {
> +    PciExDeviceConfiguration.DeviceCtl2LTR =
> + EFI_PCI_EXPRESS_NOT_APPLICABLE;  }
> +
> 
>    if (mPciExPlatformProtocol != NULL) {
>      return mPciExPlatformProtocol->NotifyDeviceState (
> --
> 2.21.0.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 10/12] PciBusDxe: New PCI Express feature Extended Tag
       [not found] ` <15F137861A640F9F.15938@groups.io>
@ 2020-02-07 20:29   ` Javeed, Ashraf
  0 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:29 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch can also be viewed in the following repo:-
https://github.com/ashrafj/edk2-staging/commit/f0d81499e79e4521630a76ae241de6def9aa03b5

Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Saturday, February 8, 2020 1:35 AM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 10/12]
> PciBusDxe: New PCI Express feature Extended Tag
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2499
> 
> This code change enables the PCI Express feature Extended Tag, in compliance
> with the PCI Express Base Specification 5, and uses the device policy under the
> following conditions:
> (1) As per the PCI Express Base Specification, all the devices under the
>     root bridge has to be set to a common applicable value
> (2) The 5b or 8b Extended Tag capability is defined in the Device Capabi-
>     lity register, and the 10b requester as well as completer is defined
>     in the Device Capability 2 register
> (3) The Extended Tag device policy would be overruled for any device if
>     it does not match with its device capabilities register
> (4) In case of multiple device policies, due to multiple devices under
>     the root bridge, the lowest applicable value will be programmed for
>     all the devices
> (5) There is no Extended Tag disable state; hence the default would be
>     5b or 8b depending upon device HW-state. The 10b requester is disabled
>     by default; hence any device policy request of 10b shall lead to 10b
>     Requester enable state from root bridge to all end devices; if all the
>     devices support 10b Requester as well as the completer capability. In
>     this scenario, the default state of 5b/8b Extended Tag state in Device
>     Control register is ignored as 10b capable devices should be able to
>     handle lower size Extended Tag packet IDs autonomously.
> 
> This programming of Extended Tag, gets the device-specific platform policy
> using the new PCI Express Platform Protocol interface (ECR version 0.8), defined
> in the below feature request:-
>   https://bugzilla.tianocore.org/show_bug.cgi?id=1954
> 
> 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 | 278
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h |  50
> ++++++++++++++++++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  |  15
> ++++++++++++++-
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h  |   4 ++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c |  36
> ++++++++++++++++++++++++++++++++++++
>  6 files changed, 383 insertions(+), 1 deletion(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> index 7e43a26..6a6f648 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> @@ -297,6 +297,7 @@ struct _PCI_IO_DEVICE {
>    PCI_FEATURE_POLICY                        SetupCTO;
>    EFI_PCI_EXPRESS_ATOMIC_OP                 SetupAtomicOp;
>    BOOLEAN                                   SetupLtr;
> +  UINT8                                     SetupExtTag;
>  };
> 
>  #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 63a243b..eaef3d3 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> @@ -1240,3 +1240,281 @@ ProgramLtr (
>    return Status;
>  }
> 
> +/**
> +  The main routine to setup the PCI Express feature Extended Tag as per
> +the
> +  device-specific platform policy, as well as in complaince with the
> +PCI Express
> +  Base specification Revision 5.
> +
> +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> +  @param PciExpressConfigurationTable  pointer to
> + PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +
> +  @retval EFI_SUCCESS                   setup of PCI feature LTR is successful.
> +**/
> +EFI_STATUS
> +SetupExtTag (
> +  IN  PCI_IO_DEVICE                             *PciDevice,
> +  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciExpressConfigurationTable
> +  )
> +{
> +  PCI_REG_PCIE_DEVICE_CAPABILITY2 DeviceCap2;
> +  PCI_REG_PCIE_DEVICE_CAPABILITY  DeviceCap;
> +  EFI_PCI_EXPRESS_EXTENDED_TAG    PciExpressExtendedTag;
> +
> +  DeviceCap.Uint32 =
> + PciDevice->PciExpressCapabilityStructure.DeviceCapability.Uint32;
> +  DeviceCap2.Uint32 =
> + PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Uint32;
> +  //
> +  // The PCI Express feature Extended Tag has to be maintained common
> + from a  // root bridge device to all its child devices.
> +  // The Device Capability 2 register is used to determine the 10b
> + Extended Tag  // capability of a device. The device capability
> + register is used to determine  // 5b/8b Extended Tag capability of a
> + device  //  if (DeviceCap2.Bits.TenBitTagCompleterSupported &
> + DeviceCap2.Bits.TenBitTagRequesterSupported) {
> +    //
> +    // device supports the 10b Extended Tag capability
> +    //
> +    PciExpressExtendedTag = EFI_PCI_EXPRESS_EXTENDED_TAG_10BIT;
> +  } else {
> +    if (DeviceCap.Bits.ExtendedTagField) {
> +      PciExpressExtendedTag = EFI_PCI_EXPRESS_EXTENDED_TAG_8BIT;
> +    } else {
> +      PciExpressExtendedTag = EFI_PCI_EXPRESS_EXTENDED_TAG_5BIT;
> +    }
> +  }
> +  if (PciDevice->SetupExtTag == EFI_PCI_EXPRESS_EXTENDED_TAG_AUTO) {
> +    PciDevice->SetupExtTag = PciExpressExtendedTag;  }  //  // in case
> + of PCI Bridge and its child devices  //  if
> + (PciExpressConfigurationTable) {
> +    //
> +    // align the Extended Tag value as per the device supported value
> +    //
> +    PciExpressConfigurationTable->ExtendedTag = MIN (
> +                                                  PciExpressExtendedTag,
> +                                                  PciExpressConfigurationTable->ExtendedTag
> +                                                  );
> +    //
> +    // check for any invalid platform policy request for the device; if true than
> +    // align with the device capability value. Else align as per platform request
> +    //
> +    if (PciDevice->SetupExtTag > PciExpressConfigurationTable->ExtendedTag) {
> +      //
> +      // setup the device Extended Tag to common value supported by all the
> devices
> +      //
> +      PciDevice->SetupExtTag = PciExpressConfigurationTable->ExtendedTag;
> +    }
> +    //
> +    // if the platform policy is to downgrade the device's Extended Tag value
> than
> +    // all the other devices in the PCI tree including the root bridge will be align
> +    // with this device override value
> +    //
> +    if (PciDevice->SetupExtTag < PciExpressConfigurationTable->ExtendedTag) {
> +      PciExpressConfigurationTable->ExtendedTag = PciDevice->SetupExtTag;
> +    }
> +  } else {
> +    //
> +    // in case of RCiEP devices or the bridge device without any child, overrule
> +    // the Extended Tag device policy if it does not match with its capability
> +    //
> +    PciDevice->SetupExtTag = MIN (
> +                              PciDevice->SetupExtTag,
> +                              PciExpressExtendedTag
> +                              );
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "ExtTag: %d [cap:%d],",
> +    PciDevice->SetupExtTag,
> +    PciExpressExtendedTag
> +    ));
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Additional routine to setup the PCI Express feature Extended Tag in
> +complaince
> +  with the PCI Express Base specification Revision, a common value for
> +all the
> +  devices in the PCI hierarchy.
> +
> +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> +  @param PciExpressConfigurationTable  pointer to
> + PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +
> +  @retval EFI_SUCCESS                   setup of PCI feature LTR is successful.
> +**/
> +EFI_STATUS
> +AlignExtTag (
> +  IN  PCI_IO_DEVICE                             *PciDevice,
> +  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciExpressConfigurationTable
> +  )
> +{
> +  if (PciExpressConfigurationTable) {
> +    //
> +    // align the Extended Tag value to a common value among all the devices
> +    //
> +    PciDevice->SetupExtTag = MIN (
> +                              PciDevice->SetupExtTag,
> +                              PciExpressConfigurationTable->ExtendedTag
> +                              );
> +  }
> +
> +  DEBUG ((
> +    DEBUG_INFO,
> +    "ExtTag: %d,",
> +    PciDevice->SetupExtTag
> +    ));
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Program the PCI Device Control 2 register for 10b Extended Tag value,
> +or the
> +  Device Control register for 5b/8b Extended Tag 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
> +ProgramExtTag (
> +  IN PCI_IO_DEVICE          *PciDevice,
> +  IN VOID                   *PciExFeatureConfiguration
> +  )
> +{
> +  PCI_REG_PCIE_DEVICE_CONTROL   DevCtl;
> +  PCI_REG_PCIE_DEVICE_CONTROL2  DevCtl2;
> +  UINT32                        Offset;
> +  UINT32                        Offset2;
> +  BOOLEAN                       OverrideDevCtl;
> +  BOOLEAN                       OverrideDevCtl2;
> +  EFI_STATUS                    Status;
> +  EFI_TPL                       OldTpl;
> +
> +  //
> +  // read the Device Control register for the Extended Tag Field Enable
> + //
> +  DevCtl.Uint16 = 0;
> +  Offset = PciDevice->PciExpressCapabilityOffset +
> +              OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);  Status
> + = PciDevice->PciIo.Pci.Read (
> +                                  &PciDevice->PciIo,
> +                                  EfiPciIoWidthUint16,
> +                                  Offset,
> +                                  1,
> +                                  &DevCtl.Uint16
> +                                  );
> +  ASSERT (Status == EFI_SUCCESS);
> +
> +  OverrideDevCtl = FALSE;
> +  //
> +  // read the Device COntrol 2 register for the 10-Bit Tag Requester
> + Enable  //
> +  DevCtl2.Uint16 = 0;
> +  Offset2 = PciDevice->PciExpressCapabilityOffset +
> +              OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2);
> + Status = PciDevice->PciIo.Pci.Read (
> +                                  &PciDevice->PciIo,
> +                                  EfiPciIoWidthUint16,
> +                                  Offset2,
> +                                  1,
> +                                  &DevCtl2.Uint16
> +                                  );
> +  ASSERT (Status == EFI_SUCCESS);
> +
> +  OverrideDevCtl2 = FALSE;
> +
> +  if (PciDevice->SetupExtTag == EFI_PCI_EXPRESS_EXTENDED_TAG_5BIT) {
> +    if (DevCtl.Bits.ExtendedTagField) {
> +      DevCtl.Bits.ExtendedTagField = 0;
> +      OverrideDevCtl = TRUE;
> +    }
> +
> +    if (DevCtl2.Bits.TenBitTagRequesterEnable) {
> +      DevCtl2.Bits.TenBitTagRequesterEnable = 0;
> +      OverrideDevCtl2 = TRUE;
> +    }
> +  }
> +  if (PciDevice->SetupExtTag == EFI_PCI_EXPRESS_EXTENDED_TAG_8BIT) {
> +    if (!DevCtl.Bits.ExtendedTagField) {
> +      DevCtl.Bits.ExtendedTagField = 1;
> +      OverrideDevCtl = TRUE;
> +    }
> +    if (DevCtl2.Bits.TenBitTagRequesterEnable) {
> +      DevCtl2.Bits.TenBitTagRequesterEnable = 0;
> +      OverrideDevCtl2 = TRUE;
> +    }
> +  }
> +  if (PciDevice->SetupExtTag == EFI_PCI_EXPRESS_EXTENDED_TAG_10BIT) {
> +    if (!DevCtl2.Bits.TenBitTagRequesterEnable) {
> +      DevCtl2.Bits.TenBitTagRequesterEnable = 1;
> +      OverrideDevCtl2 = TRUE;
> +    }
> +  }
> +
> +  if (OverrideDevCtl) {
> +
> +    DEBUG (( DEBUG_INFO, "ExtTag=%d,", DevCtl.Bits.ExtendedTagField));
> +
> +    //
> +    // 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,
> +                                    &DevCtl.Uint16
> +                                    );
> +    //
> +    // Restore TPL to its original level
> +    //
> +    gBS->RestoreTPL (OldTpl);
> +
> +    if (!EFI_ERROR(Status)) {
> +      PciDevice->PciExpressCapabilityStructure.DeviceControl.Uint16 =
> DevCtl.Uint16;
> +    } else {
> +      ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber,
> PciDevice->FunctionNumber, Offset);
> +    }
> +  } else {
> +    DEBUG (( DEBUG_INFO, "no ExtTag (%d),",
> + DevCtl.Bits.ExtendedTagField));  }
> +
> +  if (OverrideDevCtl2) {
> +
> +    DEBUG (( DEBUG_INFO, "10bExtTag=%d,",
> + DevCtl2.Bits.TenBitTagRequesterEnable));
> +
> +    //
> +    // 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,
> +                                    Offset2,
> +                                    1,
> +                                    &DevCtl2.Uint16
> +                                    );
> +    //
> +    // Restore TPL to its original level
> +    //
> +    gBS->RestoreTPL (OldTpl);
> +
> +    if (!EFI_ERROR(Status)) {
> +      PciDevice->PciExpressCapabilityStructure.DeviceControl2.Uint16 =
> DevCtl2.Uint16;
> +    } else {
> +      ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber,
> PciDevice->FunctionNumber, Offset2);
> +    }
> +  } else {
> +    DEBUG (( DEBUG_INFO, "no 10bExtTag (%d),",
> + DevCtl2.Bits.TenBitTagRequesterEnable));
> +  }
> +
> +  return Status;
> +}
> +
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> index 374fe49..1cfca54 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> @@ -243,4 +243,54 @@ ProgramLtr (
>    IN VOID                   *PciExFeatureConfiguration
>    );
> 
> +/**
> +  The main routine to setup the PCI Express feature Extended Tag as per
> +the
> +  device-specific platform policy, as well as in complaince with the
> +PCI Express
> +  Base specification Revision 5.
> +
> +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> +  @param PciFeaturesConfigurationTable  pointer to
> + PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +
> +  @retval EFI_SUCCESS                   setup of PCI feature LTR is successful.
> +**/
> +EFI_STATUS
> +SetupExtTag (
> +  IN  PCI_IO_DEVICE                             *PciDevice,
> +  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciFeaturesConfigurationTable
> +  );
> +
> +/**
> +  Additional routine to setup the PCI Express feature Extended Tag in
> +complaince
> +  with the PCI Express Base specification Revision, a common value for
> +all the
> +  devices in the PCI hierarchy.
> +
> +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> +  @param PciFeaturesConfigurationTable  pointer to
> + PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +
> +  @retval EFI_SUCCESS                   setup of PCI feature LTR is successful.
> +**/
> +EFI_STATUS
> +AlignExtTag (
> +  IN  PCI_IO_DEVICE                             *PciDevice,
> +  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciFeaturesConfigurationTable
> +  );
> +
> +/**
> +  Program the PCI Device Control 2 register for 10b Extended Tag value,
> +or the
> +  Device Control register for 5b/8b Extended Tag 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
> +ProgramExtTag (
> +  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 bdeb0d2..58d3780 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> @@ -38,7 +38,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY
> mPciExpressPlatformPolicy = {
>      //
>      // support for PCI Express feature - Extended Tag
>      //
> -    FALSE,
> +    TRUE,
>      //
>      // support for PCI Express feature - Relax Order
>      //
> @@ -140,6 +140,15 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT
> mPciExpressFeatureInitializationList[]
>    },
>    {
>      PciExpressFeatureProgramPhase,        PciExpressLtr,        ProgramLtr
> +  },
> +  {
> +    PciExpressFeatureSetupPhase,          PciExpressExtTag,     SetupExtTag
> +  },
> +  {
> +    PciExpressFeatureEntendedSetupPhase,  PciExpressExtTag,     AlignExtTag
> +  },
> +  {
> +    PciExpressFeatureProgramPhase,        PciExpressExtTag,     ProgramExtTag
>    }
>  };
> 
> @@ -675,6 +684,10 @@ CreatePciRootBridgeDeviceNode (
>      // tree
>      //
>      PciConfigTable->AtomicOpRoutingSupported    = TRUE;
> +    //
> +    // start by assuming the Extended Tag is 10b Requester capable
> +    //
> +    PciConfigTable->ExtendedTag                 =
> EFI_PCI_EXPRESS_EXTENDED_TAG_10BIT;
>    }
> 
>    RootBridgeNode->PciExFeaturesConfigurationTable  = PciConfigTable; diff --
> git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> index 5dded7c..c7cc7e5 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> @@ -94,6 +94,10 @@ struct
> _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE {
>    // the AtomicOp of the EP device
>    //
>    BOOLEAN                                   AtomicOpRoutingSupported;
> +  //
> +  // to configure a common extended tag size for all the childs of a
> + root port  //
> +  UINT8                                     ExtendedTag;
>  };
> 
>  //
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> index 83b3aa7..98d9875 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> @@ -368,6 +368,12 @@ SetupDefaultPciExpressDevicePolicy (
> 
>    PciDevice->SetupLtr = FALSE;
> 
> +  if (mPciExpressPlatformPolicy.ExtTag) {
> +    PciDevice->SetupExtTag = EFI_PCI_EXPRESS_EXTENDED_TAG_AUTO;
> +  } else {
> +    PciDevice->SetupExtTag = EFI_PCI_EXPRESS_NOT_APPLICABLE;  }
> +
>  }
> 
>  /**
> @@ -502,6 +508,15 @@ GetPciExpressDevicePolicy (
>        PciDevice->SetupLtr = FALSE;
>      }
> 
> +    //
> +    // set the device-specifci policy for the PCI Express feature Extended Tag
> +    //
> +    if (mPciExpressPlatformPolicy.ExtTag) {
> +      PciDevice->SetupExtTag = PciExpressDevicePolicy.DeviceCtlExtTag;
> +    } else {
> +      PciDevice->SetupExtTag = EFI_PCI_EXPRESS_NOT_APPLICABLE;
> +    }
> +
> 
>      DEBUG ((
>        DEBUG_INFO,
> @@ -668,6 +683,19 @@ GetPciExpressCto (
>    return EFI_PCI_EXPRESS_NOT_APPLICABLE;  }
> 
> +EFI_PCI_EXPRESS_EXTENDED_TAG
> +GetPciExpressExtTag (
> +  IN PCI_IO_DEVICE                        *PciDevice
> +  )
> +{
> +  if (PciDevice-
> >PciExpressCapabilityStructure.DeviceControl2.Bits.TenBitTagRequesterEnable)
> {
> +    return EFI_PCI_EXPRESS_EXTENDED_TAG_10BIT;
> +  } else if (PciDevice-
> >PciExpressCapabilityStructure.DeviceControl.Bits.ExtendedTagField) {
> +    return EFI_PCI_EXPRESS_EXTENDED_TAG_8BIT;
> +  } else {
> +    return EFI_PCI_EXPRESS_EXTENDED_TAG_5BIT;
> +  }
> +}
> 
>  /**
>    Notifies the platform about the current PCI Express state of the device.
> @@ -768,6 +796,14 @@ PciExpressPlatformNotifyDeviceState (
>      PciExDeviceConfiguration.DeviceCtl2LTR =
> EFI_PCI_EXPRESS_NOT_APPLICABLE;
>    }
> 
> +  //
> +  // get the device-specific state for the PCie Extended Tag in the
> + function  //  if (mPciExpressPlatformPolicy.ExtTag) {
> +    PciExDeviceConfiguration.DeviceCtlExtTag = GetPciExpressExtTag
> + (PciDevice);  } else {
> +    PciExDeviceConfiguration.DeviceCtlExtTag =
> + EFI_PCI_EXPRESS_NOT_APPLICABLE;  }
> 
>    if (mPciExPlatformProtocol != NULL) {
>      return mPciExPlatformProtocol->NotifyDeviceState (
> --
> 2.21.0.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 11/12] PciBusDxe: New PCI Express feature ASPM support
       [not found] ` <15F13786546CB2AB.15938@groups.io>
@ 2020-02-07 20:30   ` Javeed, Ashraf
  0 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:30 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch can also be viewed in the following repo:-
https://github.com/ashrafj/edk2-staging/commit/b44091c0f18fd578dbdaf2091145367042bdfba5

Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Saturday, February 8, 2020 1:35 AM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 11/12]
> PciBusDxe: New PCI Express feature ASPM support
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2500
> 
> This code change is to enable the common ASPM state for all the connected
> devices, as per the PCI Express Base Specification 5, Revision 1.
> This feature is not applicable to RCiEP, and to a vacant bridge device.
> The device policy request from platform is applied if that is applicable as per its
> Link Capability register. Since all the connected devices have to have common
> applicable ASPM value, it would be overuled as per PCI Ex- press Base
> Specification.
> The device L0s/L1 Acceptance Latency is used to measure against the L0s/L1 Exit
> Latencies comprising from Root Bridge to all its EP devices. If not applicable
> ASPM would be disabled for all the devices.
> 
> This programming of ASPM, gets the device-specific platform policy using the
> new PCI Express Platform Protocol interface (ECR version 0.8), defined in the
> below feature request:-
>   https://bugzilla.tianocore.org/show_bug.cgi?id=1954
> 
> 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 | 391
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h |  52
> ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  |  23
> ++++++++++++++++++++++-
> MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h  |  14 ++++++++++++++
> MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c |  45
> +++++++++++++++++++++++++++++++++++++++++++++
>  6 files changed, 525 insertions(+), 1 deletion(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> index 6a6f648..b5caffe 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> @@ -298,6 +298,7 @@ struct _PCI_IO_DEVICE {
>    EFI_PCI_EXPRESS_ATOMIC_OP                 SetupAtomicOp;
>    BOOLEAN                                   SetupLtr;
>    UINT8                                     SetupExtTag;
> +  UINT8                                     SetupAspm;
>  };
> 
>  #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 eaef3d3..5e350e7 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> @@ -1518,3 +1518,394 @@ ProgramExtTag (
>    return Status;
>  }
> 
> +/**
> +  Set the ASPM device policy as per the device's link capability.
> +**/
> +UINT8
> +SetAspmPolicy (
> +  IN UINT8  PciExpressLinkCapAspm
> +  )
> +{
> +  switch (PciExpressLinkCapAspm) {
> +    case 0:
> +      //
> +      // cannot support ASPM state, disable
> +      //
> +      return EFI_PCI_EXPRESS_ASPM_DISABLE;
> +    case 1:
> +      //
> +      // supports only ASPM L0s state
> +      //
> +      return EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT;
> +    case 2:
> +      //
> +      // supports only ASPM L1 state
> +      //
> +      return EFI_PCI_EXPRESS_ASPM_L1_SUPPORT;
> +    case 3:
> +      //
> +      // supports both L0s and L1 ASPM states
> +      //
> +      return EFI_PCI_EXPRESS_ASPM_L0S_L1_SUPPORT;
> +  }
> +  return EFI_PCI_EXPRESS_ASPM_DISABLE;
> +}
> +
> +/**
> +  The main routine to setup the PCI Express feature ASPM as per the
> +  device-specific platform policy, as well as in complaince with the
> +PCI Express
> +  Base specification Revision 5.
> +
> +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> +  @param PciExpressConfigurationTable  pointer to
> + PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +
> +  @retval EFI_SUCCESS                   setup of PCI feature LTR is successful.
> +**/
> +EFI_STATUS
> +SetupAspm (
> +  IN  PCI_IO_DEVICE                             *PciDevice,
> +  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciExpressConfigurationTable
> +  )
> +{
> +  PCI_REG_PCIE_LINK_CAPABILITY            PciExLinkCap;
> +  PCI_REG_PCIE_DEVICE_CAPABILITY          PciExpressDeviceCapability;
> +  BOOLEAN                                 AlignAspmPolicy;
> +
> +  PciExLinkCap.Uint32 =
> + PciDevice->PciExpressCapabilityStructure.LinkCapability.Uint32;
> +  PciExpressDeviceCapability.Uint32 =
> + PciDevice->PciExpressCapabilityStructure.DeviceCapability.Uint32;
> +  //
> +  // ASPM support is only applicable to root bridge and its child
> + devices. Not  // applicable to empty bridge devices or RCiEP devices
> + //  if (PciExpressConfigurationTable) {
> +    PciExpressConfigurationTable->L0sExitLatency = MAX (
> +                    PciExpressConfigurationTable->L0sExitLatency,
> +                    (UINT8)PciExLinkCap.Bits.L0sExitLatency
> +                    );
> +    PciExpressConfigurationTable->L1ExitLatency = MAX (
> +                    PciExpressConfigurationTable->L1ExitLatency,
> +                    (UINT8)PciExLinkCap.Bits.L1ExitLatency
> +                    );
> +    if (PciDevice->SetupAspm == EFI_PCI_EXPRESS_ASPM_AUTO) {
> +      //
> +      // set the ASPM support as per device's link capability
> +      //
> +      PciDevice->SetupAspm = SetAspmPolicy ((UINT8)PciExLinkCap.Bits.Aspm);
> +    } else {
> +      //
> +      // Check the ASPM device policy is applicable to the link capability.
> +      // In case of invalid device policy, there are 2 options:
> +      // (1) ASPM disable -> platform request rightly denied, and no ASPM
> +      // (2) set as per the device capability -> platform request rightly denied,
> +      //      but still set applicable power management
> +      // this implementation shall take option 2 to overule invalid platform
> request
> +      // and go with applicable policy as per device capability
> +      //
> +      switch (SetAspmPolicy ((UINT8)PciExLinkCap.Bits.Aspm)) {
> +        case EFI_PCI_EXPRESS_ASPM_DISABLE:
> +          PciDevice->SetupAspm = EFI_PCI_EXPRESS_ASPM_DISABLE;
> +          break;
> +        case EFI_PCI_EXPRESS_ASPM_L1_SUPPORT:
> +          if (PciDevice->SetupAspm == EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT) {
> +            //
> +            // not applicable, set as per device's link capability
> +            //
> +            PciDevice->SetupAspm = EFI_PCI_EXPRESS_ASPM_L1_SUPPORT;
> +          }
> +          break;
> +        case EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT:
> +          if (PciDevice->SetupAspm == EFI_PCI_EXPRESS_ASPM_L1_SUPPORT) {
> +            //
> +            // not applicable, set as per device's link capability
> +            //
> +            PciDevice->SetupAspm = EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT;
> +          }
> +          break;
> +      }
> +    }
> +    //
> +    // set the ASPM policy to minimum state among all the devices links
> +    //
> +    PciExpressConfigurationTable->AspmSupport = MIN (
> +                                                  PciExpressConfigurationTable->AspmSupport,
> +                                                  PciDevice->SetupAspm
> +                                                  );
> +    //
> +    // check the common ASPM value applicable as per this device capability, if
> +    // not applicable disable the ASPM for all the devices
> +    //
> +    if (
> +      (PciExpressConfigurationTable->AspmSupport ==
> EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT
> +        && SetAspmPolicy ((UINT8)PciExLinkCap.Bits.Aspm) ==
> EFI_PCI_EXPRESS_ASPM_L1_SUPPORT)
> +      ||
> +      (PciExpressConfigurationTable->AspmSupport ==
> EFI_PCI_EXPRESS_ASPM_L1_SUPPORT
> +        && SetAspmPolicy ((UINT8)PciExLinkCap.Bits.Aspm) ==
> EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT)
> +      ) {
> +      //
> +      // disable the ASPM
> +      //
> +      PciExpressConfigurationTable->AspmSupport =
> EFI_PCI_EXPRESS_ASPM_DISABLE;
> +      PciDevice->SetupAspm = PciExpressConfigurationTable->AspmSupport;
> +    }
> +
> +    if (PciExpressConfigurationTable->AspmSupport !=
> EFI_PCI_EXPRESS_ASPM_DISABLE) {
> +      //
> +      // in case of ASPM policy is not to disable the ASPM support, check other
> +      // condition of EP device L0s/L1 acceptance latency with the L0s/L1 exit
> +      // latencies comprising from this endpoint all the way up to root complex
> +      // root port, to determine whether the ASPM L0s/L1 entry can be used with
> +      // no loss of performance
> +      //
> +      if (!IS_PCI_BRIDGE (&PciDevice->Pci)) {
> +
> +        switch (PciExpressConfigurationTable->AspmSupport) {
> +          case EFI_PCI_EXPRESS_ASPM_L0S_L1_SUPPORT:
> +            if (
> +                PciExpressDeviceCapability.Bits.EndpointL0sAcceptableLatency >=
> PciExpressConfigurationTable->L0sExitLatency
> +                && PciExpressDeviceCapability.Bits.EndpointL1AcceptableLatency >=
> PciExpressConfigurationTable->L1ExitLatency
> +            ) {
> +              //
> +              // both the L0s & L1 acceptance of this endpoint device is greater
> +              // than or equal to all of the comprised L0s & L1 exit latencies
> +              // thus good to set the ASPM to L0s & L1 state
> +              //
> +              AlignAspmPolicy = TRUE;
> +            } else {
> +              //
> +              // in case the EP device L0s and L1 Acceptance latency does not match
> +              // with the comprised L0s & L1 exit latencies than disable the ASPM
> +              // state
> +              //
> +              AlignAspmPolicy = FALSE;
> +            }
> +            break;
> +
> +          case EFI_PCI_EXPRESS_ASPM_L1_SUPPORT:
> +            if (
> +                PciExpressDeviceCapability.Bits.EndpointL1AcceptableLatency >=
> PciExpressConfigurationTable->L1ExitLatency
> +            ) {
> +              //
> +              // the endpoint device L1 acceptance latency meets the all the
> +              // comprised L1 exit latencies of all the devices from the bridge
> +              // hence ASPM L1 is applicable state for the PCI tree
> +              //
> +              AlignAspmPolicy = TRUE;
> +            } else {
> +              //
> +              // in case the EP device L1 Acceptance latency does not match
> +              // with the comprised L1 exit latencies than disable the ASPM
> +              // state
> +              //
> +              AlignAspmPolicy = FALSE;
> +            }
> +            break;
> +
> +          case EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT:
> +            if (
> +                PciExpressDeviceCapability.Bits.EndpointL0sAcceptableLatency >=
> PciExpressConfigurationTable->L0sExitLatency
> +            ) {
> +              //
> +              // the endpoint device L0s acceptance latency meets the all the
> +              // comprised L0s exit latencies of all the devices from the bridge
> +              // hence ASPM L0s is applicable state for the PCI tree
> +              //
> +              AlignAspmPolicy = TRUE;
> +            } else {
> +              //
> +              // in case the EP device L0s Acceptance latency does not match
> +              // with the comprised L0s exit latencies than disable the ASPM
> +              // state
> +              //
> +              AlignAspmPolicy = FALSE;
> +            }
> +            break;
> +        }
> +      } else {
> +        //
> +        // align the bridge with the global common ASPM value
> +        //
> +        AlignAspmPolicy = TRUE;
> +      }
> +    } else {
> +      //
> +      // ASPM is disabled for all the devices
> +      //
> +      AlignAspmPolicy = FALSE;
> +    }
> +
> +    if (AlignAspmPolicy) {
> +      //
> +      // reset the device's ASPM policy to common minimum value
> +      //
> +      if (PciDevice->SetupAspm != PciExpressConfigurationTable->AspmSupport) {
> +        PciDevice->SetupAspm = PciExpressConfigurationTable->AspmSupport;
> +      }
> +    } else {
> +      //
> +      // disable the ASPM
> +      //
> +      PciExpressConfigurationTable->AspmSupport =
> EFI_PCI_EXPRESS_ASPM_DISABLE;
> +      PciDevice->SetupAspm = PciExpressConfigurationTable->AspmSupport;
> +    }
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "Aspm: %d [cap:%d],",
> +      PciDevice->SetupAspm,
> +      (PciExLinkCap.Bits.Aspm + 1)
> +      ));
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Setup of PCI Express feature ASPM in the
> +PciExpressFeatureEntendedSetupPhase
> +**/
> +EFI_STATUS
> +AlignAspm (
> +  IN  PCI_IO_DEVICE                             *PciDevice,
> +  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciExpressConfigurationTable
> +  )
> +{
> +  //
> +  // ASPM support is only applicable to root bridge and its child
> +devices. Not
> +  // applicable to empty bridge devices or RCiEP devices
> +  //
> +  if (PciExpressConfigurationTable) {
> +    //
> +    // reset the device's ASPM policy to common minimum ASPM value
> +    //
> +    if (PciDevice->SetupAspm != PciExpressConfigurationTable->AspmSupport) {
> +      PciDevice->SetupAspm = PciExpressConfigurationTable->AspmSupport;
> +    }
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "Aspm: %d,",
> +      PciDevice->SetupAspm
> +      ));
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Get the ASPM value from the ASPM device policy.
> +**/
> +UINT8
> +GetAspmValue (
> +  IN UINT8  AspmPolicy
> +  )
> +{
> +  switch (AspmPolicy) {
> +    case EFI_PCI_EXPRESS_ASPM_DISABLE:
> +      //
> +      // ASPM disable
> +      //
> +      return 0;
> +    case EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT:
> +      //
> +      // ASPM L0s state
> +      //
> +      return 1;
> +    case EFI_PCI_EXPRESS_ASPM_L1_SUPPORT:
> +      //
> +      // ASPM L1 state
> +      //
> +      return 2;
> +    case EFI_PCI_EXPRESS_ASPM_L0S_L1_SUPPORT:
> +      //
> +      // L0s and L1 ASPM states
> +      //
> +      return 3;
> +  }
> +  return 0;
> +}
> +
> +/**
> +  Program the PCIe Link Control register ASPM Control field; 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
> +ProgramAspm (
> +  IN PCI_IO_DEVICE          *PciDevice,
> +  IN VOID                   *PciExFeatureConfiguration
> +  )
> +{
> +  PCI_REG_PCIE_LINK_CONTROL     LinkCtl;
> +  UINT32                        Offset;
> +  EFI_STATUS                    Status;
> +  EFI_TPL                       OldTpl;
> +  UINT8                         AspmValue;
> +
> +  //
> +  // ASPM support is only applicable to root bridge and its child
> + devices. Not  // applicable to empty bridge devices or RCiEP devices
> + //  if (!PciExFeatureConfiguration) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  //
> +  // read the link Control register for the ASPM Control  //
> +  LinkCtl.Uint16 = 0;
> +  Offset = PciDevice->PciExpressCapabilityOffset +
> +              OFFSET_OF (PCI_CAPABILITY_PCIEXP, LinkControl);  Status =
> + PciDevice->PciIo.Pci.Read (
> +                                  &PciDevice->PciIo,
> +                                  EfiPciIoWidthUint16,
> +                                  Offset,
> +                                  1,
> +                                  &LinkCtl.Uint16
> +                                  );
> +  ASSERT (Status == EFI_SUCCESS);
> +
> +  AspmValue = GetAspmValue (PciDevice->SetupAspm);  if (AspmValue !=
> + LinkCtl.Bits.AspmControl) {
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "Aspm: %d,",
> +      AspmValue
> +      ));
> +    //
> +    // 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,
> +                                    &LinkCtl.Uint16
> +                                    );
> +    //
> +    // Restore TPL to its original level
> +    //
> +    gBS->RestoreTPL (OldTpl);
> +
> +    if (!EFI_ERROR (Status)) {
> +      PciDevice->PciExpressCapabilityStructure.LinkControl.Uint16 =
> LinkCtl.Uint16;
> +    } else {
> +      ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber,
> PciDevice->FunctionNumber, Offset);
> +      return Status;
> +    }
> +  } else {
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "No Aspm (%d),",
> +      AspmValue
> +      ));
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> index 1cfca54..351c61e 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> @@ -9,6 +9,15 @@ SPDX-License-Identifier: BSD-2-Clause-Patent  #ifndef
> _EFI_PCI_EXPRESS_FEATURES_H_  #define _EFI_PCI_EXPRESS_FEATURES_H_
> 
> +//
> +// PCIe L0s Exit Latencies declarations //
> +#define PCIE_LINK_CAPABILITY_L0S_EXIT_LATENCY_64NS  0   // less than 64ns
> +
> +//
> +// PCIe L1 Exit latencies declarations
> +//
> +#define PCIE_LINK_CAPABILITY_L1_EXIT_LATENCY_1US    0   // less than 1us
> 
>  /**
>    The main routine which process the PCI feature Max_Payload_Size as per the
> @@ -293,4 +302,47 @@ ProgramExtTag (
>    IN VOID                   *PciExFeatureConfiguration
>    );
> 
> +/**
> +  The main routine to setup the PCI Express feature ASPM as per the
> +  device-specific platform policy, as well as in complaince with the
> +PCI Express
> +  Base specification Revision 5.
> +
> +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> +  @param PciFeaturesConfigurationTable  pointer to
> + PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +
> +  @retval EFI_SUCCESS                   setup of PCI feature LTR is successful.
> +**/
> +EFI_STATUS
> +SetupAspm (
> +  IN  PCI_IO_DEVICE                             *PciDevice,
> +  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciFeaturesConfigurationTable
> +  );
> +
> +/**
> +  Setup of PCI Express feature ASPM in the
> +PciExpressFeatureEntendedSetupPhase
> +**/
> +EFI_STATUS
> +AlignAspm (
> +  IN  PCI_IO_DEVICE                             *PciDevice,
> +  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciFeaturesConfigurationTable
> +  );
> +
> +/**
> +  Program the PCIe Link Control register ASPM Control field; 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
> +ProgramAspm (
> +  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 58d3780..24781c6 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> @@ -50,7 +50,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY
> mPciExpressPlatformPolicy = {
>      //
>      // support for PCI Express feature - ASPM state
>      //
> -    FALSE,
> +    TRUE,
>      //
>      // support for PCI Express feature - Common Clock Configuration
>      //
> @@ -96,6 +96,15 @@ BOOLEAN   mPciExpressGetPlatformPolicyComplete =
> FALSE;
>  //
>  PCI_EXPRESS_FEATURE_INITIALIZATION_POINT
> mPciExpressFeatureInitializationList[] = {
> 
> +  {
> +    PciExpressFeatureSetupPhase,          PciExpressAspm,       SetupAspm
> +  },
> +  {
> +    PciExpressFeatureEntendedSetupPhase,  PciExpressAspm,       AlignAspm
> +  },
> +  {
> +    PciExpressFeatureProgramPhase,        PciExpressAspm,       ProgramAspm
> +  },
>    {
>      PciExpressFeatureSetupPhase,          PciExpressMps,        SetupMaxPayloadSize
>    },
> @@ -688,6 +697,18 @@ CreatePciRootBridgeDeviceNode (
>      // start by assuming the Extended Tag is 10b Requester capable
>      //
>      PciConfigTable->ExtendedTag                 =
> EFI_PCI_EXPRESS_EXTENDED_TAG_10BIT;
> +    //
> +    // initial state set to ASPM L0s and L1 both
> +    //
> +    PciConfigTable->AspmSupport                 =
> EFI_PCI_EXPRESS_ASPM_L0S_L1_SUPPORT;
> +    //
> +    // start by assuming less than 64ns of L0s Exit Latency
> +    //
> +    PciConfigTable->L0sExitLatency              =
> PCIE_LINK_CAPABILITY_L0S_EXIT_LATENCY_64NS;
> +    //
> +    // start by assuming less than 1us of L1 Exit Latency
> +    //
> +    PciConfigTable->L1ExitLatency               =
> PCIE_LINK_CAPABILITY_L1_EXIT_LATENCY_1US;
>    }
> 
>    RootBridgeNode->PciExFeaturesConfigurationTable  = PciConfigTable; diff --
> git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> index c7cc7e5..5e0f43b 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> @@ -98,6 +98,20 @@ struct
> _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE {
>    // to configure a common extended tag size for all the childs of a root port
>    //
>    UINT8                                     ExtendedTag;
> +  //
> +  // to configure common ASPM state for all the devices link  //
> +  UINT8                                     AspmSupport;
> +  //
> +  // to record maximum L0s Exit Latency among all the devices starting
> + from root  // bridge device to its downstream bridge and its endpoint
> + device  //
> +  UINT8                                     L0sExitLatency;
> +  //
> +  // to record maximum L1 Exit Latency among all the devices starting
> + from root  // bridge device to its downstream bridge and its endpoint
> + device  //
> +  UINT8                                     L1ExitLatency;
>  };
> 
>  //
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> index 98d9875..f301557 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> @@ -374,6 +374,16 @@ SetupDefaultPciExpressDevicePolicy (
>      PciDevice->SetupExtTag = EFI_PCI_EXPRESS_NOT_APPLICABLE;
>    }
> 
> +  //
> +  // default device policy for device's link ASPM  //  if
> + (mPciExpressPlatformPolicy.Aspm) {
> +    PciDevice->SetupAspm = EFI_PCI_EXPRESS_ASPM_AUTO;  } else {
> +    PciDevice->SetupAspm = EFI_PCI_EXPRESS_NOT_APPLICABLE;  }
> +
> +
>  }
> 
>  /**
> @@ -517,6 +527,14 @@ GetPciExpressDevicePolicy (
>        PciDevice->SetupExtTag = EFI_PCI_EXPRESS_NOT_APPLICABLE;
>      }
> 
> +    //
> +    // set the device-specific policy for the PCI Express feature ASPM
> +    //
> +    if (mPciExpressPlatformPolicy.Aspm) {
> +      PciDevice->SetupAspm = PciExpressDevicePolicy.LinkCtlASPMState;
> +    } else {
> +      PciDevice->SetupAspm = EFI_PCI_EXPRESS_NOT_APPLICABLE;
> +    }
> 
>      DEBUG ((
>        DEBUG_INFO,
> @@ -697,6 +715,24 @@ GetPciExpressExtTag (
>    }
>  }
> 
> +EFI_PCI_EXPRESS_ASPM_SUPPORT
> +GetPciExpressAspmState (
> +  IN PCI_IO_DEVICE                        *PciDevice
> +  )
> +{
> +  switch (PciDevice-
> >PciExpressCapabilityStructure.LinkControl.Bits.AspmControl) {
> +    case 0:
> +      return EFI_PCI_EXPRESS_ASPM_DISABLE;
> +    case 1:
> +      return EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT;
> +    case 2:
> +      return EFI_PCI_EXPRESS_ASPM_L1_SUPPORT;
> +    case 3:
> +      return EFI_PCI_EXPRESS_ASPM_L0S_L1_SUPPORT;
> +  }
> +  return EFI_PCI_EXPRESS_NOT_APPLICABLE; }
> +
>  /**
>    Notifies the platform about the current PCI Express state of the device.
> 
> @@ -805,6 +841,15 @@ PciExpressPlatformNotifyDeviceState (
>      PciExDeviceConfiguration.DeviceCtlExtTag =
> EFI_PCI_EXPRESS_NOT_APPLICABLE;
>    }
> 
> +  //
> +  // get the device-specific state for PCIe ASPM state  //  if
> + (mPciExpressPlatformPolicy.Aspm) {
> +    PciExDeviceConfiguration.LinkCtlASPMState = GetPciExpressAspmState
> + (PciDevice);  } else {
> +    PciExDeviceConfiguration.LinkCtlASPMState =
> + EFI_PCI_EXPRESS_NOT_APPLICABLE;  }
> +
>    if (mPciExPlatformProtocol != NULL) {
>      return mPciExPlatformProtocol->NotifyDeviceState (
>                                      mPciExPlatformProtocol,
> --
> 2.21.0.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 12/12] PciBusDxe: New PCI Express feature Common CLock Config
       [not found] ` <15F13786E92D19E9.15938@groups.io>
@ 2020-02-07 20:31   ` Javeed, Ashraf
  0 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-07 20:31 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch can also be viewed in the following repo:-
https://github.com/ashrafj/edk2-staging/commit/34a6c33558aed624ca95f719e5df4f3363f7cb05

Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Saturday, February 8, 2020 1:35 AM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 12/12]
> PciBusDxe: New PCI Express feature Common CLock Config
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2500
> 
> This code change enforces the Link Control register CCC field as per the
> following conditions:-
> (1) When the Clock Configuration device policy for all the devices are
>     set to EFI_PCI_EXPRESS_CLK_CFG_AUTO:-
>     - Based on the Link Status register's Slot Clock Configuration field,
>       all the devices CCC value shall be aligned
> (2) When the Clock Configuration device policy for one or more devices
>     are either set to EFI_PCI_EXPRESS_CLK_CFG_ASYNCH or EFI_PCI_EXPRESS_
>     CLK_CFG_COMMON
>     - enforces the same clock configuration for all the devices from
>       root bridge
> Note that the recommendation to the platform is to always provide the device
> policy as EFI_PCI_EXPRESS_CLK_CFG_AUTO.
> In case for any device its Link Control register CCC field is required to be
> changed based on its present HW-state, than Link Retraining is preformed on the
> downstream ports as per the PCI Express Base specification.
> 
> This programming of CCC, gets the device-specific platform policy using the new
> PCI Express Platform Protocol interface (ECR version 0.8), defined in the below
> feature request:-
>   https://bugzilla.tianocore.org/show_bug.cgi?id=1954
> 
> 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 | 267
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h |  51
> +++++++++++++++++++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  |  20
> ++++++++++++++++++--
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h  |   9 +++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c |  28
> ++++++++++++++++++++++++++++
>  6 files changed, 374 insertions(+), 2 deletions(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> index b5caffe..34f482d 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> @@ -299,6 +299,7 @@ struct _PCI_IO_DEVICE {
>    BOOLEAN                                   SetupLtr;
>    UINT8                                     SetupExtTag;
>    UINT8                                     SetupAspm;
> +  EFI_PCI_EXPRESS_COMMON_CLOCK_CFG          SetupCcc;
>  };
> 
>  #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 5e350e7..1e2f4a4 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> @@ -1909,3 +1909,270 @@ ProgramAspm (
>    return EFI_SUCCESS;
>  }
> 
> +/**
> +  The main routine to setup the PCI Express feature Common Clock
> +configuration
> +  as per the device-specific platform policy, as well as in complaince
> +with the
> +  PCI Express Base specification Revision 5.
> +
> +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> +  @param PciExpressConfigurationTable  pointer to
> + PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +
> +  @retval EFI_SUCCESS                   setup of PCI feature LTR is successful.
> +**/
> +EFI_STATUS
> +SetupCommonClkCfg (
> +  IN  PCI_IO_DEVICE                             *PciDevice,
> +  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciExpressConfigurationTable
> +  )
> +{
> +  PCI_REG_PCIE_LINK_STATUS                      LinkSts;
> +
> +  LinkSts.Uint16 =
> + PciDevice->PciExpressCapabilityStructure.LinkStatus.Uint16;
> +
> +  //
> +  // Common Clock Configuration is only applicable to root bridge and
> +its child
> +  // devices. Not applicable to empty bridge devices or RCiEP devices
> +  //
> +  if (PciExpressConfigurationTable) {
> +    if (PciDevice->SetupCcc == EFI_PCI_EXPRESS_CLK_CFG_AUTO) {
> +      //
> +      // as per the PCI Express Base Specification, the link status register
> +      // slot clock configuration of the opposing side of link devices indicate
> +      // the clock configuration properly; hence rely on this data to configure
> +      // the link's clock configuration
> +      //
> +      if (LinkSts.Bits.SlotClockConfiguration) {
> +        PciExpressConfigurationTable->CommonClockConfiguration = TRUE;
> +      } else {
> +        PciExpressConfigurationTable->CommonClockConfiguration = FALSE;
> +      }
> +    } else if (PciDevice->SetupCcc == EFI_PCI_EXPRESS_CLK_CFG_ASYNCH) {
> +      //
> +      // platform override to any device shall change for other device on the
> +      // link, the clock configuration has to be maintained common across all
> +      // the devices
> +      //
> +      PciExpressConfigurationTable->CommonClockConfiguration = FALSE;
> +    } else {
> +      PciExpressConfigurationTable->CommonClockConfiguration = TRUE;
> +    }
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Program the PCIe Link Control register Coomon Clock Configuration
> +field; 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
> +ProgramCcc (
> +  IN PCI_IO_DEVICE                            *PciDevice,
> +  IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciExFeatureConfiguration
> +  )
> +{
> +  PCI_REG_PCIE_LINK_CONTROL     LinkCtl;
> +  UINT32                        Offset;
> +  EFI_STATUS                    Status;
> +  EFI_TPL                       OldTpl;
> +
> +  //
> +  // Common Clock Configuration is only applicable to root bridge and
> + its child  // devices. Not applicable to empty bridge devices or RCiEP
> + devices  //  if (!PciExFeatureConfiguration) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  //
> +  // read the link Control register for the ASPM Control  //
> +  LinkCtl.Uint16 = 0;
> +  Offset = PciDevice->PciExpressCapabilityOffset +
> +              OFFSET_OF (PCI_CAPABILITY_PCIEXP, LinkControl);  Status =
> + PciDevice->PciIo.Pci.Read (
> +                                  &PciDevice->PciIo,
> +                                  EfiPciIoWidthUint16,
> +                                  Offset,
> +                                  1,
> +                                  &LinkCtl.Uint16
> +                                  );
> +  ASSERT (Status == EFI_SUCCESS);
> +
> +  //
> +  // in case Common Clock Configuration is required to be programmed in
> + the  // downstream ports from the root bridge devices in the heirarchy
> + //  if (PciExFeatureConfiguration->CommonClockConfiguration == TRUE) {
> +    if (LinkCtl.Bits.CommonClockConfiguration == 0) {
> +      LinkCtl.Bits.CommonClockConfiguration = 1;
> +      //
> +      // current clock mode does not match hence retrain of the link at bridge
> device
> +      // is required
> +      //
> +      PciExFeatureConfiguration->LinkReTrain = TRUE;
> +    }
> +  } else {
> +    //
> +    // in case the opposing devices of the PCI link have different reference clock
> +    // set the link control register CCC field accordingly
> +    //
> +    if (LinkCtl.Bits.CommonClockConfiguration) {
> +      LinkCtl.Bits.CommonClockConfiguration = 0;
> +      //
> +      // current clock mode does not match hence retrain of the link at bridge
> device
> +      // is required
> +      //
> +      PciExFeatureConfiguration->LinkReTrain = TRUE;
> +    }
> +  }
> +  //
> +  // use the retrain flag as a sigm to also update the CCC of the link
> + register  //  if (PciExFeatureConfiguration->LinkReTrain == TRUE) {
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "CCC: %d,",
> +      LinkCtl.Bits.CommonClockConfiguration
> +      ));
> +    //
> +    // 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,
> +                                    &LinkCtl.Uint16
> +                                    );
> +    //
> +    // Restore TPL to its original level
> +    //
> +    gBS->RestoreTPL (OldTpl);
> +
> +    if (!EFI_ERROR (Status)) {
> +      PciDevice->PciExpressCapabilityStructure.LinkControl.Uint16 =
> LinkCtl.Uint16;
> +    } else {
> +      ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber,
> PciDevice->FunctionNumber, Offset);
> +      return Status;
> +    }
> +  } else {
> +    PciDevice->PciExpressCapabilityStructure.LinkControl.Uint16 =
> LinkCtl.Uint16;
> +    DEBUG ((
> +      DEBUG_INFO,
> +      "No CCC (%d),",
> +      LinkCtl.Bits.CommonClockConfiguration
> +      ));
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Second phase of programming for Common Clock COnfiguration,
> +conditoonally done
> +  only on the downstream ports (bridge devices only).
> +
> +  @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
> +EnforceCcc (
> +  IN PCI_IO_DEVICE                            *PciDevice,
> +  IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciExFeatureConfiguration
> +  )
> +{
> +  PCI_REG_PCIE_LINK_CONTROL     LinkCtl;
> +  PCI_REG_PCIE_LINK_STATUS      LinkSts;
> +  PCI_REG_PCIE_CAPABILITY       PciExCap;
> +  UINT32                        Offset;
> +  EFI_STATUS                    Status;
> +  EFI_TPL                       OldTpl;
> +
> +  //
> +  // Common Clock Configuration is only applicable to root bridge and
> + its child  // devices. Not applicable to empty bridge devices or RCiEP
> + devices  //  if (!PciExFeatureConfiguration) {
> +    return EFI_SUCCESS;
> +  }
> +  PciExCap.Uint16 =
> + PciDevice->PciExpressCapabilityStructure.Capability.Uint16;
> +  LinkCtl.Uint16 =
> + PciDevice->PciExpressCapabilityStructure.LinkControl.Uint16;
> +
> +  //
> +  // retrain the bridge device (downstream ports including the root
> + port)  //  if (PciExFeatureConfiguration->LinkReTrain == TRUE) {
> +    if (IS_PCI_BRIDGE (&PciDevice->Pci)) {
> +      //
> +      // retrain of the PCI link happens for CCC change only on the downstream
> +      // ports
> +      //
> +      if (
> +        PciExCap.Bits.DevicePortType == PCIE_DEVICE_PORT_TYPE_ROOT_PORT
> +        || PciExCap.Bits.DevicePortType ==
> PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT
> +        ) {
> +        LinkCtl.Bits.RetrainLink = 1;
> +        Offset = PciDevice->PciExpressCapabilityOffset +
> +                     OFFSET_OF (PCI_CAPABILITY_PCIEXP, LinkControl);
> +        //
> +        // 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,
> +                                        &LinkCtl.Uint16
> +                                        );
> +        //
> +        // Restore TPL to its original level
> +        //
> +        gBS->RestoreTPL (OldTpl);
> +
> +        if (!EFI_ERROR (Status)) {
> +          //
> +          // poll the link status register for the link retrain to be complete
> +          //
> +          Offset = PciDevice->PciExpressCapabilityOffset +
> +                               OFFSET_OF (PCI_CAPABILITY_PCIEXP, LinkStatus);
> +          do {
> +            Status = PciDevice->PciIo.Pci.Read (
> +                                            &PciDevice->PciIo,
> +                                            EfiPciIoWidthUint16,
> +                                            Offset,
> +                                            1,
> +                                            &LinkSts.Uint16
> +                                            );
> +            ASSERT (Status == EFI_SUCCESS);
> +          } while (LinkSts.Bits.LinkTraining);
> +        } else {
> +          ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber,
> PciDevice->FunctionNumber, Offset);
> +          return Status;
> +        }
> +      }
> +      //
> +      // ignore the upstream bridge devices
> +      //
> +    }
> +    //
> +    // not applicable to endpoint devices
> +    //
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> index 351c61e..33df337 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> @@ -345,4 +345,55 @@ ProgramAspm (
>    IN VOID                   *PciExFeatureConfiguration
>    );
> 
> +/**
> +  The main routine to setup the PCI Express feature Common Clock
> +configuration
> +  as per the device-specific platform policy, as well as in complaince
> +with the
> +  PCI Express Base specification Revision 5.
> +
> +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> +  @param PciExpressConfigurationTable  pointer to
> + PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +
> +  @retval EFI_SUCCESS                   setup of PCI feature LTR is successful.
> +**/
> +EFI_STATUS
> +SetupCommonClkCfg (
> +  IN  PCI_IO_DEVICE                             *PciDevice,
> +  IN  PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciExpressConfigurationTable
> +  );
> +
> +/**
> +  Program the PCIe Link Control register Coomon Clock Configuration
> +field; 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
> +ProgramCcc (
> +  IN PCI_IO_DEVICE                            *PciDevice,
> +  IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciExFeatureConfiguration
> +  );
> +
> +/**
> +  Second phase of programming for Common Clock COnfiguration,
> +conditoonally done
> +  only on the downstream ports (bridge devices only).
> +
> +  @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
> +EnforceCcc (
> +  IN PCI_IO_DEVICE                            *PciDevice,
> +  IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE
> +*PciExFeatureConfiguration
> +  );
>  #endif
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> index 24781c6..4d3641c 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> @@ -54,7 +54,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY
> mPciExpressPlatformPolicy = {
>      //
>      // support for PCI Express feature - Common Clock Configuration
>      //
> -    FALSE,
> +    TRUE,
>      //
>      // support for PCI Express feature - Extended Sync
>      //
> @@ -95,7 +95,15 @@ BOOLEAN   mPciExpressGetPlatformPolicyComplete =
> FALSE;
>  // PCI Express feature initialization phase handle routines  //
> PCI_EXPRESS_FEATURE_INITIALIZATION_POINT
> mPciExpressFeatureInitializationList[] = {
> -
> +  {
> +    PciExpressFeatureSetupPhase,          PciExpressCcc,        SetupCommonClkCfg
> +  },
> +  {
> +    PciExpressFeatureEntendedSetupPhase,  PciExpressCcc,        ProgramCcc
> +  },
> +  {
> +    PciExpressFeatureProgramPhase,        PciExpressCcc,        EnforceCcc
> +  },
>    {
>      PciExpressFeatureSetupPhase,          PciExpressAspm,       SetupAspm
>    },
> @@ -709,6 +717,14 @@ CreatePciRootBridgeDeviceNode (
>      // start by assuming less than 1us of L1 Exit Latency
>      //
>      PciConfigTable->L1ExitLatency               =
> PCIE_LINK_CAPABILITY_L1_EXIT_LATENCY_1US;
> +    //
> +    // default link retrain is not required
> +    //
> +    PciConfigTable->LinkReTrain                 = FALSE;
> +    //
> +    // start by assuming no common clock configuration mode for the device's
> link
> +    //
> +    PciConfigTable->CommonClockConfiguration    = FALSE;
>    }
> 
>    RootBridgeNode->PciExFeaturesConfigurationTable  = PciConfigTable; diff --
> git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> index 5e0f43b..481bd90 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> @@ -112,6 +112,15 @@ struct
> _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE {
>    // bridge device to its downstream bridge and its endpoint device
>    //
>    UINT8                                     L1ExitLatency;
> +  //
> +  // flag to indicate the link training is required in the devices of
> + downstream  // ports  //
> +  BOOLEAN                                   LinkReTrain;
> +  //
> +  // link status slot clock configuration  //
> +  BOOLEAN                                   CommonClockConfiguration;
>  };
> 
>  //
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> index f301557..bf380ab 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> @@ -383,6 +383,14 @@ SetupDefaultPciExpressDevicePolicy (
>      PciDevice->SetupAspm = EFI_PCI_EXPRESS_NOT_APPLICABLE;
>    }
> 
> +  //
> +  // default device policy for the device's link clock configuration
> + //  if (mPciExpressPlatformPolicy.Ccc) {
> +    PciDevice->SetupCcc = EFI_PCI_EXPRESS_CLK_CFG_AUTO;  } else {
> +    PciDevice->SetupCcc = EFI_PCI_EXPRESS_NOT_APPLICABLE;  }
> 
>  }
> 
> @@ -536,6 +544,15 @@ GetPciExpressDevicePolicy (
>        PciDevice->SetupAspm = EFI_PCI_EXPRESS_NOT_APPLICABLE;
>      }
> 
> +    //
> +    // set the device policy for the PCI Express feature Common Clock
> Configuration
> +    //
> +    if (mPciExpressPlatformPolicy.Ccc) {
> +      PciDevice->SetupCcc = PciExpressDevicePolicy.LinkCtlCommonClkCfg;
> +    } else {
> +      PciDevice->SetupCcc = EFI_PCI_EXPRESS_NOT_APPLICABLE;
> +    }
> +
>      DEBUG ((
>        DEBUG_INFO,
>        "[device policy: platform]"
> @@ -850,6 +867,17 @@ PciExpressPlatformNotifyDeviceState (
>      PciExDeviceConfiguration.LinkCtlASPMState =
> EFI_PCI_EXPRESS_NOT_APPLICABLE;
>    }
> 
> +  //
> +  // get the device-specific Common CLock Configuration value  //  if
> + (mPciExpressPlatformPolicy.Ccc) {
> +    PciExDeviceConfiguration.LinkCtlCommonClkCfg =
> +        PciDevice-
> >PciExpressCapabilityStructure.LinkControl.Bits.CommonClockConfiguration ?
> +            EFI_PCI_EXPRESS_CLK_CFG_COMMON :
> + EFI_PCI_EXPRESS_CLK_CFG_ASYNCH;  } else {
> +    PciExDeviceConfiguration.LinkCtlCommonClkCfg =
> + EFI_PCI_EXPRESS_NOT_APPLICABLE;  }
> +
>    if (mPciExPlatformProtocol != NULL) {
>      return mPciExPlatformProtocol->NotifyDeviceState (
>                                      mPciExPlatformProtocol,
> --
> 2.21.0.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe: Setup for PCI Express features
  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
  0 siblings, 1 reply; 36+ messages in thread
From: Ni, Ray @ 2020-02-10  7:20 UTC (permalink / raw)
  To: Javeed, Ashraf, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

> > +  PCI_CAPABILITY_PCIEXP                     PciExpressCapabilityStructure;
1. To Align with existing field "Pci", how about rename it to
   "PciExpressCapability" (no "Structure" suffix)?


2. I see that only GetPciExpressProtocol() in PciPlatformSupport.c is used in this patch.
    All other functions in PciFeatureSupport.c andPciPlatformSupport.c are not used.
    It makes the reviewers confused about how those unused functions can be used.
    You should remove these unused functions in this patch and add them in later patches
    when the code logic calls them.

Thanks,
Ray

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12] MdeModulePkg/PciBusDxe: Setup PCI Express init phase
  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
  0 siblings, 1 reply; 36+ messages in thread
From: Ni, Ray @ 2020-02-10  7:37 UTC (permalink / raw)
  To: Javeed, Ashraf, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

> > +      Status = EnumeratePciExpressFeatures (
1. "enumerate" means "visit". But I think this function is not just visiting the features but also
     programming them. So, How about "ProgramPciExpressFeatures"?
     (I gave a similar review comment in last time review in Dec.)

2. In mail https://edk2.groups.io/g/devel/message/52399 I proposed to simplify to 4 phases.
    Did you find any issue with my proposal?

Thanks,
Ray

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] PciBusDxe: New PCI Express features
  2020-02-07 20:04 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] PciBusDxe: New PCI Express features Javeed, Ashraf
                   ` (23 preceding siblings ...)
       [not found] ` <15F13786E92D19E9.15938@groups.io>
@ 2020-02-10  7:40 ` Ni, Ray
  2020-02-10  8:34   ` Javeed, Ashraf
  24 siblings, 1 reply; 36+ messages in thread
From: Ni, Ray @ 2020-02-10  7:40 UTC (permalink / raw)
  To: Javeed, Ashraf, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

Ashraf,
I reviewed the first and second patches.

Can you please check my review comments to your December's patches and make sure
either your new code changes followed the comments, or we continue discuss the review
comments if you don't agree?

I just found some code changes didn't follow as comments suggested.

Thanks,
Ray


> -----Original Message-----
> From: Javeed, Ashraf <ashraf.javeed@intel.com>
> Sent: Saturday, February 8, 2020 4:05 AM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] PciBusDxe: New
> PCI Express features
> 
> The PciBusDxe is enhanced to initialize 10 PCI Express features (patch
> index 3 to 12).
> All these PCI Express features attributes are defined based on the new
> PCI Express Platform Protocol definition (as per its ECR draft version
> 0.8): https://bugzilla.tianocore.org/show_bug.cgi?id=1954.
> For MPS, MRRS:-
>     https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> For RO, NS, CTO:-
>     https://bugzilla.tianocore.org/show_bug.cgi?id=2313
> For AtomicOp, Extended Tag, LTR:-
>     https://bugzilla.tianocore.org/show_bug.cgi?id=2499
> For ASPM, CCC:-
>     https://bugzilla.tianocore.org/show_bug.cgi?id=2500
> 
> 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>
> 
> 
> Ashraf Javeed (12):
>   MdeModulePkg/PciBusDxe: Setup for PCI Express features
>   MdeModulePkg/PciBusDxe: Setup PCI Express init phase
>   PciBusDxe: New PCI Express feature Max_Payload_Size
>   PciBusDxe: New PCI Express feature Max_Read_Req_Size
>   PciBusDxe: New PCI Express feature Relax Ordering
>   PciBusDxe: New PCI Express feature No-Snoop
>   PciBusDxe: New PCI Express feature Completion Timeout
>   PciBusDxe: New PCI Express feature AtomicOp
>   PciBusDxe: New PCI Express feature LTR
>   PciBusDxe: New PCI Express feature Extended Tag
>   PciBusDxe: New PCI Express feature ASPM support
>   PciBusDxe: New PCI Express feature Common CLock Config
> 
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c               |    6 ++-
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h               |   25 ++++++++++-
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf          |   11 ++++-
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c     |  181
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
> -----------
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c |   12 +++++-
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c   | 2178
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h   |  399
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c    | 1019
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h    |  304
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c   |  902
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h   |  119
> ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  11 files changed, 5116 insertions(+), 40 deletions(-)
>  create mode 100644 MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
>  create mode 100644 MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
>  create mode 100644 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
>  create mode 100644 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
>  create mode 100644 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
>  create mode 100644 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> 
> --
> 2.21.0.windows.1


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe: Setup for PCI Express features
  2020-02-10  7:20     ` Ni, Ray
@ 2020-02-10  8:26       ` Javeed, Ashraf
  2020-02-10  8:37         ` Ni, Ray
  0 siblings, 1 reply; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-10  8:26 UTC (permalink / raw)
  To: Ni, Ray, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

My comments below.

Thanks
Ashraf

> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Monday, February 10, 2020 12:50 PM
> To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12]
> MdeModulePkg/PciBusDxe: Setup for PCI Express features
> 
> > > +  PCI_CAPABILITY_PCIEXP                     PciExpressCapabilityStructure;
> 1. To Align with existing field "Pci", how about rename it to
>    "PciExpressCapability" (no "Structure" suffix)?
> 
As per PCI Express Base Specification, the feature name is "PCI Express Capability Structure" and I have used the same type although the data structure defined for the same has not used it. Is this really important that I have to remove the "Structure" from its name?
> 
> 2. I see that only GetPciExpressProtocol() in PciPlatformSupport.c is used in this
> patch.
>     All other functions in PciFeatureSupport.c andPciPlatformSupport.c are not
> used.
>     It makes the reviewers confused about how those unused functions can be
> used.
>     You should remove these unused functions in this patch and add them in later
> patches
>     when the code logic calls them.
> 
All the other main routines of the PciPlatformSupport.c are called from the code of PciFeatureSupport.c.
All the routines of the PciFeatureSupport.c are called from within itself, and its main routine that defines the integration of PCI Express feature initialization is defined in the following second patch.
If required, I can combine both the patches into one patch, which gives the basic structure of the PCI Express feature initialization in the PciBusDxe.

> Thanks,
> Ray

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12] MdeModulePkg/PciBusDxe: Setup PCI Express init phase
  2020-02-10  7:37     ` Ni, Ray
@ 2020-02-10  8:32       ` Javeed, Ashraf
  2020-02-10  8:46         ` Ni, Ray
  0 siblings, 1 reply; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-10  8:32 UTC (permalink / raw)
  To: Ni, Ray, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

Thanks
Ashraf

> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Monday, February 10, 2020 1:07 PM
> To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12]
> MdeModulePkg/PciBusDxe: Setup PCI Express init phase
> 
> > > +      Status = EnumeratePciExpressFeatures (
> 1. "enumerate" means "visit". But I think this function is not just visiting the
> features but also
>      programming them. So, How about "ProgramPciExpressFeatures"?
>      (I gave a similar review comment in last time review in Dec.)
> 
Actually I have already used the "ProgramPciExpressFeatures" in one of the sub-phases of the PCI Express initialization code...do you have any other name for this? How about "ConfigurePciExpressFeatures"?

> 2. In mail https://edk2.groups.io/g/devel/message/52399 I proposed to simplify
> to 4 phases.
>     Did you find any issue with my proposal?
I did simplify to 4 phases, please check. The fifth phase is to report out the device state to the platform through the protocol interface "NotifyDeviceState".

> 
> Thanks,
> Ray

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] PciBusDxe: New PCI Express features
  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
  0 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-10  8:34 UTC (permalink / raw)
  To: Ni, Ray, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

Ray,
I have responded to your review comments.
These patches has been changed accommodating your previous review comments.
Please check.

Thanks
Ashraf

> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Monday, February 10, 2020 1:10 PM
> To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] PciBusDxe:
> New PCI Express features
> 
> Ashraf,
> I reviewed the first and second patches.
> 
> Can you please check my review comments to your December's patches and
> make sure either your new code changes followed the comments, or we
> continue discuss the review comments if you don't agree?
> 
> I just found some code changes didn't follow as comments suggested.
> 
> Thanks,
> Ray
> 
> 
> > -----Original Message-----
> > From: Javeed, Ashraf <ashraf.javeed@intel.com>
> > Sent: Saturday, February 8, 2020 4:05 AM
> > To: devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > <hao.a.wu@intel.com>; Ni, Ray <ray.ni@intel.com>
> > Subject: [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] PciBusDxe: New
> > PCI Express features
> >
> > The PciBusDxe is enhanced to initialize 10 PCI Express features (patch
> > index 3 to 12).
> > All these PCI Express features attributes are defined based on the new
> > PCI Express Platform Protocol definition (as per its ECR draft version
> > 0.8): https://bugzilla.tianocore.org/show_bug.cgi?id=1954.
> > For MPS, MRRS:-
> >     https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> > For RO, NS, CTO:-
> >     https://bugzilla.tianocore.org/show_bug.cgi?id=2313
> > For AtomicOp, Extended Tag, LTR:-
> >     https://bugzilla.tianocore.org/show_bug.cgi?id=2499
> > For ASPM, CCC:-
> >     https://bugzilla.tianocore.org/show_bug.cgi?id=2500
> >
> > 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>
> >
> >
> > Ashraf Javeed (12):
> >   MdeModulePkg/PciBusDxe: Setup for PCI Express features
> >   MdeModulePkg/PciBusDxe: Setup PCI Express init phase
> >   PciBusDxe: New PCI Express feature Max_Payload_Size
> >   PciBusDxe: New PCI Express feature Max_Read_Req_Size
> >   PciBusDxe: New PCI Express feature Relax Ordering
> >   PciBusDxe: New PCI Express feature No-Snoop
> >   PciBusDxe: New PCI Express feature Completion Timeout
> >   PciBusDxe: New PCI Express feature AtomicOp
> >   PciBusDxe: New PCI Express feature LTR
> >   PciBusDxe: New PCI Express feature Extended Tag
> >   PciBusDxe: New PCI Express feature ASPM support
> >   PciBusDxe: New PCI Express feature Common CLock Config
> >
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c               |    6 ++-
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h               |   25 ++++++++++-
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf          |   11 ++++-
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c     |  181
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
> ---
> > -----------
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c |   12 +++++-
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c   | 2178
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > +++++++++++++++++++++++++++
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h   |  399
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > ++++++++++++++++++++++++++++++++++++++++++
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c    | 1019
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > ++++++++++++++++++++++++++++++++++++++++++++++++
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h    |  304
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > +
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c   |  902
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h   |  119
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  11 files changed, 5116 insertions(+), 40 deletions(-)  create mode
> > 100644 MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
> >  create mode 100644
> > MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
> >  create mode 100644 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> >  create mode 100644 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> >  create mode 100644
> > MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> >  create mode 100644
> > MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> >
> > --
> > 2.21.0.windows.1


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe: Setup for PCI Express features
  2020-02-10  8:26       ` Javeed, Ashraf
@ 2020-02-10  8:37         ` Ni, Ray
  2020-02-11  3:59           ` Javeed, Ashraf
  0 siblings, 1 reply; 36+ messages in thread
From: Ni, Ray @ 2020-02-10  8:37 UTC (permalink / raw)
  To: Javeed, Ashraf, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A



> -----Original Message-----
> From: Javeed, Ashraf <ashraf.javeed@intel.com>
> Sent: Monday, February 10, 2020 4:26 PM
> To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe: Setup for PCI
> Express features
> 
> My comments below.
> 
> Thanks
> Ashraf
> 
> > -----Original Message-----
> > From: Ni, Ray <ray.ni@intel.com>
> > Sent: Monday, February 10, 2020 12:50 PM
> > To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12]
> > MdeModulePkg/PciBusDxe: Setup for PCI Express features
> >
> > > > +  PCI_CAPABILITY_PCIEXP                     PciExpressCapabilityStructure;
> > 1. To Align with existing field "Pci", how about rename it to
> >    "PciExpressCapability" (no "Structure" suffix)?
> >
> As per PCI Express Base Specification, the feature name is "PCI Express Capability Structure" and I have used the same type
> although the data structure defined for the same has not used it. Is this really important that I have to remove the
> "Structure" from its name?
I prefer to use shorter name if possible and it also aligns to the existing code style.
Is it really that important that you keep the "Structure" to align to the PCIE spec? 😊

> >
> > 2. I see that only GetPciExpressProtocol() in PciPlatformSupport.c is used in this
> > patch.
> >     All other functions in PciFeatureSupport.c andPciPlatformSupport.c are not
> > used.
> >     It makes the reviewers confused about how those unused functions can be
> > used.
> >     You should remove these unused functions in this patch and add them in later
> > patches
> >     when the code logic calls them.
> >
> All the other main routines of the PciPlatformSupport.c are called from the code of PciFeatureSupport.c.
> All the routines of the PciFeatureSupport.c are called from within itself, and its main routine that defines the integration
> of PCI Express feature initialization is defined in the following second patch.
> If required, I can combine both the patches into one patch, which gives the basic structure of the PCI Express feature
> initialization in the PciBusDxe.
Are all the routines in the two C files called from the main routine in PciBus driver?
The answer with this patch is NO.
The guideline is one patch serves one purpose and it's better to be as small as possible so that the change can be easier to review.
With this guideline, combining both patches to one big one is not preferred.

> 
> > Thanks,
> > Ray

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12] MdeModulePkg/PciBusDxe: Setup PCI Express init phase
  2020-02-10  8:32       ` Javeed, Ashraf
@ 2020-02-10  8:46         ` Ni, Ray
  2020-02-11  7:14           ` Javeed, Ashraf
  0 siblings, 1 reply; 36+ messages in thread
From: Ni, Ray @ 2020-02-10  8:46 UTC (permalink / raw)
  To: Javeed, Ashraf, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

My proposal defines four phases: Initialize, Scan, Program, Finalize. The four phases are very similar to your
December's patch with just one phase opt out.

As below:
---BEGIN----
Each feature needs to provide function pointers for each phase and NULL means the feature doesn't
need to do anything in the specific phase.
With that, we can define a structure:
Typedef struct {
  BOOLEAN                          Enable;
  PCIE_FEATURE_INITILAIZE Initialize;
  PCIE_FEATURE_SCAN  Scan;
  PCIE_FEATURE_PROGRAM Program;
  PCIE_FEATURE_FINALIZE Finalize;
} PCIE_FEATURE_ENTRY;

With that, we can define a module level global variable:
PCIE_FEATURE_ENTRY mPcieFeatures[] = {
  { TRUE, MaxPayloadInitialize, MaxPayloadScan, MaxPayloadProgram, MaxPayloadFinalize},
  { TRUE, MaxReadRequestInitialize, MaxReadRequestScan, MaxReadRequestProgram, MaxReadRequestFinalize},
  { TRUE, NULL, NULL, RelaxOrderProgram, NULL},
  { TRUE, NULL, CompletionTimeoutScan, CompletionTimeoutProgram, NULL },
  ...
};

PCIE_FEATURE_ENTRY.Enable can be set to FALSE according to the platform policy.

The enable of PCIE features can be written as a feature agnostic for-loop.
This can make the new feature enabling code easy to add and review.
---END----

While your today's patch defines a different 5-phase as below.
typedef enum {
  PciExpressFeaturePreProcessPhase,
  PciExpressFeatureSetupPhase,
  PciExpressFeatureEntendedSetupPhase,
  PciExpressFeatureProgramPhase,
  PciExpressFeatureEndPhase
} PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE;

I don't think they are very similar. And your new proposal is far different from what you proposed
in December's patch.
Did you meet any issues that triggered this new proposal?

Thanks,
Ray

> -----Original Message-----
> From: Javeed, Ashraf <ashraf.javeed@intel.com>
> Sent: Monday, February 10, 2020 4:33 PM
> To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12] MdeModulePkg/PciBusDxe: Setup PCI Express
> init phase
> 
> Thanks
> Ashraf
> 
> > -----Original Message-----
> > From: Ni, Ray <ray.ni@intel.com>
> > Sent: Monday, February 10, 2020 1:07 PM
> > To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12]
> > MdeModulePkg/PciBusDxe: Setup PCI Express init phase
> >
> > > > +      Status = EnumeratePciExpressFeatures (
> > 1. "enumerate" means "visit". But I think this function is not just visiting the
> > features but also
> >      programming them. So, How about "ProgramPciExpressFeatures"?
> >      (I gave a similar review comment in last time review in Dec.)
> >
> Actually I have already used the "ProgramPciExpressFeatures" in one of the sub-phases of the PCI Express initialization
> code...do you have any other name for this? How about "ConfigurePciExpressFeatures"?
> 
> > 2. In mail https://edk2.groups.io/g/devel/message/52399 I proposed to simplify
> > to 4 phases.
> >     Did you find any issue with my proposal?
> I did simplify to 4 phases, please check. The fifth phase is to report out the device state to the platform through the
> protocol interface "NotifyDeviceState".
> 
> >
> > Thanks,
> > Ray

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe: Setup for PCI Express features
  2020-02-10  8:37         ` Ni, Ray
@ 2020-02-11  3:59           ` Javeed, Ashraf
  0 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-11  3:59 UTC (permalink / raw)
  To: Ni, Ray, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A



> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Monday, February 10, 2020 2:08 PM
> To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12]
> MdeModulePkg/PciBusDxe: Setup for PCI Express features
> 
> 
> 
> > -----Original Message-----
> > From: Javeed, Ashraf <ashraf.javeed@intel.com>
> > Sent: Monday, February 10, 2020 4:26 PM
> > To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > <hao.a.wu@intel.com>
> > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > 01/12] MdeModulePkg/PciBusDxe: Setup for PCI Express features
> >
> > My comments below.
> >
> > Thanks
> > Ashraf
> >
> > > -----Original Message-----
> > > From: Ni, Ray <ray.ni@intel.com>
> > > Sent: Monday, February 10, 2020 12:50 PM
> > > To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > <hao.a.wu@intel.com>
> > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > > 01/12]
> > > MdeModulePkg/PciBusDxe: Setup for PCI Express features
> > >
> > > > > +  PCI_CAPABILITY_PCIEXP                     PciExpressCapabilityStructure;
> > > 1. To Align with existing field "Pci", how about rename it to
> > >    "PciExpressCapability" (no "Structure" suffix)?
> > >
> > As per PCI Express Base Specification, the feature name is "PCI
> > Express Capability Structure" and I have used the same type although
> > the data structure defined for the same has not used it. Is this really important
> that I have to remove the "Structure" from its name?
> I prefer to use shorter name if possible and it also aligns to the existing code
> style.
> Is it really that important that you keep the "Structure" to align to the PCIE spec?
> 😊
I think it is better to have a right name here.
> 
> > >
> > > 2. I see that only GetPciExpressProtocol() in PciPlatformSupport.c
> > > is used in this patch.
> > >     All other functions in PciFeatureSupport.c
> > > andPciPlatformSupport.c are not used.
> > >     It makes the reviewers confused about how those unused functions
> > > can be used.
> > >     You should remove these unused functions in this patch and add
> > > them in later patches
> > >     when the code logic calls them.
> > >
> > All the other main routines of the PciPlatformSupport.c are called from the
> code of PciFeatureSupport.c.
> > All the routines of the PciFeatureSupport.c are called from within
> > itself, and its main routine that defines the integration of PCI Express feature
> initialization is defined in the following second patch.
> > If required, I can combine both the patches into one patch, which
> > gives the basic structure of the PCI Express feature initialization in the
> PciBusDxe.
> Are all the routines in the two C files called from the main routine in PciBus
> driver?
> The answer with this patch is NO.
> The guideline is one patch serves one purpose and it's better to be as small as
> possible so that the change can be easier to review.
> With this guideline, combining both patches to one big one is not preferred.
> 
The purpose of the patch was to set up general code infrastructure, so that the PCI Express feature initialization routines can be added in the following patches.
If I have to break this code infrastructure into smaller patches than not all the routines are expected to be called from the main routine of the PciBusDxe. From this development, only 2 routines are called from the main routine of the PciBusDxe, hence the first 2 patches. If I have to break down further than don’t expect that all the routines shall be called from main routine.
From the developer perspective this task of breaking the code into smaller patches is very difficult. This actually delays the main goal of the changes.

> > > Thanks,
> > > Ray

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12] MdeModulePkg/PciBusDxe: Setup PCI Express init phase
  2020-02-10  8:46         ` Ni, Ray
@ 2020-02-11  7:14           ` Javeed, Ashraf
  0 siblings, 0 replies; 36+ messages in thread
From: Javeed, Ashraf @ 2020-02-11  7:14 UTC (permalink / raw)
  To: Ni, Ray, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A



> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Monday, February 10, 2020 2:16 PM
> To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12]
> MdeModulePkg/PciBusDxe: Setup PCI Express init phase
> 
> My proposal defines four phases: Initialize, Scan, Program, Finalize. The four
> phases are very similar to your December's patch with just one phase opt out.
> 
> As below:
> ---BEGIN----
> Each feature needs to provide function pointers for each phase and NULL means
> the feature doesn't need to do anything in the specific phase.
> With that, we can define a structure:
> Typedef struct {
>   BOOLEAN                          Enable;
>   PCIE_FEATURE_INITILAIZE Initialize;
>   PCIE_FEATURE_SCAN  Scan;
>   PCIE_FEATURE_PROGRAM Program;
>   PCIE_FEATURE_FINALIZE Finalize;
> } PCIE_FEATURE_ENTRY;
> 
> With that, we can define a module level global variable:
> PCIE_FEATURE_ENTRY mPcieFeatures[] = {
>   { TRUE, MaxPayloadInitialize, MaxPayloadScan, MaxPayloadProgram,
> MaxPayloadFinalize},
>   { TRUE, MaxReadRequestInitialize, MaxReadRequestScan,
> MaxReadRequestProgram, MaxReadRequestFinalize},
>   { TRUE, NULL, NULL, RelaxOrderProgram, NULL},
>   { TRUE, NULL, CompletionTimeoutScan, CompletionTimeoutProgram, NULL },
>   ...
> };
> 
> PCIE_FEATURE_ENTRY.Enable can be set to FALSE according to the platform
> policy.
> 
> The enable of PCIE features can be written as a feature agnostic for-loop.
> This can make the new feature enabling code easy to add and review.
> ---END----
> 
I have seen this, in essence the concept is adopted, but it has been further enhanced to achieve the objectives.

> While your today's patch defines a different 5-phase as below.
> typedef enum {
  //
  // preprocessing applicable only to few PCI Express features to bind all devices
  // under the common root bridge device (root port), that would be useful to align
  // all devices with a common value. This would be optional phase based on the
  // type of the PCI Express feature to be programmed based on platform policy
  //
>   PciExpressFeaturePreProcessPhase,

  //
  // mandatory phase to setup the PCI Express feature to its applicable attribute,
  // based on its device-specific platform policies, matching with its device capabilities
  //
>   PciExpressFeatureSetupPhase,

  //
  // optional phase primarily to align all devices, specially required when PCI
  // switch is present in the hierarchy, applicable to certain few PCI Express
  // features only
  //
>   PciExpressFeatureEntendedSetupPhase,

  //
  // mandatory programming phase to complete the configuration of the PCI Express
  // features
  //
>   PciExpressFeatureProgramPhase,

  //
  // optional phase to clean up temporary buffers, like those that were prepared
  // during the preprocessing phase above
  //
>   PciExpressFeatureEndPhase
> } PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE;
> 
> I don't think they are very similar. And your new proposal is far different from
> what you proposed in December's patch.
> Did you meet any issues that triggered this new proposal?
> 
The details are as follows:-
(1) Your proposal of data structure PCIE_FEATURE_ENTRY will add up 1 byte for Boolean and 8 * 4 bytes for 4 different types of function pointers. For 10 PCIe features, it is going to take 330 bytes fixed size.
(2) I wanted to optimized to avoid fixed size, added the phase, and feature Id enum (4 bytes each), with just single pointer to function for the feature initialization phase into the data structure PCI_EXPRESS_FEATURE_INITIALIZATION_POINT, since I know that many don't need all the phases for initialization. So, the total size turn outs to be 400 bytes, which is not what I had desired. But, I can further optimized the data structure PCI_EXPRESS_FEATURE_INITIALIZATION_POINT so that its size can be 10 bytes. With this, for 10 PCIe features initialization the routines defined in the "mPciExpressFeatureInitializationList " shall be 250 bytes, shall be less compare to using the PCIE_FEATURE_ENTRY; this can be in next version.
(3) The pointer-to-function name to be used as subphases appears fine for PCIe feature specific action, but not for general action items, like free up of temporary memory allocated resources. Explicit declarations has helped in optimizing a code for both feature specific and for common action items, which the subsequent patches reflect those.
(4) The phase names are matching as per their scope of actions, whose comments in the code section are also captured (above). 
(5) As per the nature of the PCIe feature to align common value among all the PCI devices, every node in the tree has to be traversed twice to arrive at final value for the initialization (especially required for the PCIe switch multi-port device, to connect to other EndPoint devices), and the next phase would be the actual write to the PCI device. The phases for traversing are the - PciExpressFeatureSetupPhase, PciExpressFeatureEntendedSetupPhase; and write operation phase is - PciExpressFeatureProgramPhase.
(6) The preprocessing phase is - PciExpressFeaturePreProcessPhase, where the resources are allocated specific to PCIe feature, that needs to be bind to every root bridge device. 
(7) The final phase is - PciExpressFeatureEndPhase; this phase is use for 2 purpose: (i) to invoke the NotifyDeviceState() to indicate to platform about its current device state after the PCIe feature programming is complete, and (ii) free up the resource allocated in the preprocessing phase.

> Thanks,
> Ray
> 
> > -----Original Message-----
> > From: Javeed, Ashraf <ashraf.javeed@intel.com>
> > Sent: Monday, February 10, 2020 4:33 PM
> > To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > <hao.a.wu@intel.com>
> > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > 02/12] MdeModulePkg/PciBusDxe: Setup PCI Express init phase
> >
> > Thanks
> > Ashraf
> >
> > > -----Original Message-----
> > > From: Ni, Ray <ray.ni@intel.com>
> > > Sent: Monday, February 10, 2020 1:07 PM
> > > To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > <hao.a.wu@intel.com>
> > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > > 02/12]
> > > MdeModulePkg/PciBusDxe: Setup PCI Express init phase
> > >
> > > > > +      Status = EnumeratePciExpressFeatures (
> > > 1. "enumerate" means "visit". But I think this function is not just
> > > visiting the features but also
> > >      programming them. So, How about "ProgramPciExpressFeatures"?
> > >      (I gave a similar review comment in last time review in Dec.)
> > >
> > Actually I have already used the "ProgramPciExpressFeatures" in one of
> > the sub-phases of the PCI Express initialization code...do you have any other
> name for this? How about "ConfigurePciExpressFeatures"?
> >
> > > 2. In mail https://edk2.groups.io/g/devel/message/52399 I proposed
> > > to simplify to 4 phases.
> > >     Did you find any issue with my proposal?
> > I did simplify to 4 phases, please check. The fifth phase is to report
> > out the device state to the platform through the protocol interface
> "NotifyDeviceState".
> >
> > >
> > > Thanks,
> > > Ray

^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2020-02-11  7:15 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] PciBusDxe: New PCI Express feature Completion Timeout Javeed, Ashraf
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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox