public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New PCI features Max_Payload_Size, Max_Read_Req_Size
@ 2019-09-23 14:20 Javeed, Ashraf
  2019-10-14  6:57 ` Ni, Ray
  0 siblings, 1 reply; 12+ messages in thread
From: Javeed, Ashraf @ 2019-09-23 14:20 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

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

The EDK2 Kernel PciBusDxe driver is enhanced to enable the configuration
of PCI features like Max_Payload_Size and Max_Read_Req_Size.

Max_Payload_Size:- The PCI Device Control register provides this feature
register field which controls the maximum data packet (TLP) size that a
PCI device should maintain as a requester. The PCI Bus driver is required
to maintain a highest common value supported by all the PCI devices in a
PCIe hierarchy, especially in case of isochronous applications.

Max_Read_Req_Size:- The PCI Device Control register provides this feature
register field which controls the maximum memory read request size that a
PCI device should maintain as a requester. The PCI Bus driver is required
to maintain a common value, same as Max_Payload_Size, in case of
isochronous applications only; or else, it should maintain the user
requested value uniformly in a PCIe hierarchy (PCI root port and its
downstream devices).

The PCI Base Specification 4 Revision 1 contains detailed information
about these features. The EDK2 PCI Bus driver needs to enable the
configuration of these features as per the PCI Base specification.

The EDK2 PCI Bus driver also needs to take the PCI device-specific
platform policy into the consideration while programming these features;
thus the code changes to support these, is explicitly dependent on the
new PCI Platform Protocol interface definition defined in the below
record:-
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.c               |   23 ++------------
 MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h               |   14 ++++++++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf          |    9 +++++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c     |  229 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------
 MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c        |  139 ++++++++++++++++++++--------------------------------------------------------------
 MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c |   34 ++++++++++++--------
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c    | 1601 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h    |  201 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c   |  565 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h   |  193 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c   |   15 +--------
 MdeModulePkg/MdeModulePkg.dec                         |   10 ++++++
 12 files changed, 2797 insertions(+), 236 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
index b020ce50ce..2503b298f4 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 - 2019, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -34,8 +34,6 @@ BOOLEAN                                       gFullEnumeration     = TRUE;
 UINT64                                        gAllOne              = 0xFFFFFFFFFFFFFFFFULL;
 UINT64                                        gAllZero             = 0;
 
-EFI_PCI_PLATFORM_PROTOCOL                     *gPciPlatformProtocol;
-EFI_PCI_OVERRIDE_PROTOCOL                     *gPciOverrideProtocol;
 EDKII_IOMMU_PROTOCOL                          *mIoMmuProtocol;
 
 
@@ -266,24 +264,7 @@ PciBusDriverBindingStart (
   // If PCI Platform protocol is available, get it now.
   // If the platform implements this, it must be installed before BDS phase
   //
-  gPciPlatformProtocol = NULL;
-  gBS->LocateProtocol (
-        &gEfiPciPlatformProtocolGuid,
-        NULL,
-        (VOID **) &gPciPlatformProtocol
-        );
-
-  //
-  // If PCI Platform protocol doesn't exist, try to Pci Override Protocol.
-  //
-  if (gPciPlatformProtocol == NULL) {
-    gPciOverrideProtocol = NULL;
-    gBS->LocateProtocol (
-          &gEfiPciOverrideProtocolGuid,
-          NULL,
-          (VOID **) &gPciOverrideProtocol
-          );
-  }
+  GetPciPlatformProtocol ();
 
   if (mIoMmuProtocol == NULL) {
     gBS->LocateProtocol (
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index 504a1b1c12..7955bf8a26 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -27,6 +27,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Protocol/PciOverride.h>
 #include <Protocol/PciEnumerationComplete.h>
 #include <Protocol/IoMmu.h>
+#include <Protocol/PciPlatform2.h>
+#include <Protocol/PciOverride2.h>
 
 #include <Library/DebugLib.h>
 #include <Library/UefiDriverEntryPoint.h>
@@ -79,6 +81,7 @@ typedef enum {
 #include "PciPowerManagement.h"
 #include "PciHotPlugSupport.h"
 #include "PciLib.h"
+#include "PciFeatureSupport.h"
 
 #define VGABASE1  0x3B0
 #define VGALIMIT1 0x3BB
@@ -263,9 +266,13 @@ struct _PCI_IO_DEVICE {
 
   BOOLEAN                                   IsPciExp;
   //
-  // For SR-IOV
+  // For PCI Express Capability List Structure
   //
   UINT8                                     PciExpressCapabilityOffset;
+  PCI_CAPABILITY_PCIEXP                     PciExpStruct;
+  //
+  // For SR-IOV
+  //
   UINT32                                    AriCapabilityOffset;
   UINT32                                    SrIovCapabilityOffset;
   UINT32                                    MrIovCapabilityOffset;
@@ -279,6 +286,11 @@ struct _PCI_IO_DEVICE {
   // This field is used to support this case.
   //
   UINT16                                    BridgeIoAlignment;
+  //
+  // Other PCI features setup flags
+  //
+  UINT8                                     SetupMPS;
+  UINT8                                     SetupMRRS;
 };
 
 #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 05c22025b8..13768d7ded 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 - 2019, 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,8 @@
   gEfiLoadFile2ProtocolGuid                       ## SOMETIMES_PRODUCES
   gEdkiiIoMmuProtocolGuid                         ## SOMETIMES_CONSUMES
   gEfiLoadedImageDevicePathProtocolGuid           ## CONSUMES
+  gEfiPciPlatformProtocol2Guid                     ## SOMETIMES_CONSUMES
+  gEfiPciOverrideProtocol2Guid                     ## SOMETIMES_CONSUMES
 
 [FeaturePcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport      ## CONSUMES
@@ -104,6 +110,7 @@
   gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport                  ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport                ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration    ## SOMETIMES_CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures                    ## CONSUMES
 
 [UserExtensions.TianoCore."ExtraFiles"]
   PciBusDxeExtra.uni
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
index b7832c6970..0f76ab1cd5 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
@@ -170,6 +170,8 @@ DestroyRootBridgeByHandle (
 
     if (Temp->Handle == Controller) {
 
+      DestroyRootBridgePciFeaturesConfigCompletionList ( Temp);
+
       RemoveEntryList (CurrentLink);
 
       DestroyPciDeviceTree (Temp);
@@ -208,8 +210,6 @@ RegisterPciDevice (
   )
 {
   EFI_STATUS          Status;
-  VOID                *PlatformOpRomBuffer;
-  UINTN               PlatformOpRomSize;
   EFI_PCI_IO_PROTOCOL *PciIo;
   UINT8               Data8;
   BOOLEAN             HasEfiImage;
@@ -244,49 +244,13 @@ RegisterPciDevice (
     //
     // Get the OpRom provided by platform
     //
-    if (gPciPlatformProtocol != NULL) {
-      Status = gPciPlatformProtocol->GetPciRom (
-                                       gPciPlatformProtocol,
-                                       PciIoDevice->Handle,
-                                       &PlatformOpRomBuffer,
-                                       &PlatformOpRomSize
-                                       );
-      if (!EFI_ERROR (Status)) {
-        PciIoDevice->EmbeddedRom    = FALSE;
-        PciIoDevice->RomSize        = (UINT32) PlatformOpRomSize;
-        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
-        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
-        //
-        // For OpROM read from gPciPlatformProtocol:
-        // Add the Rom Image to internal database for later PCI light enumeration
-        //
-        PciRomAddImageMapping (
-          NULL,
-          PciIoDevice->PciRootBridgeIo->SegmentNumber,
-          PciIoDevice->BusNumber,
-          PciIoDevice->DeviceNumber,
-          PciIoDevice->FunctionNumber,
-          PciIoDevice->PciIo.RomImage,
-          PciIoDevice->PciIo.RomSize
-          );
-      }
-    } else if (gPciOverrideProtocol != NULL) {
-      Status = gPciOverrideProtocol->GetPciRom (
-                                       gPciOverrideProtocol,
-                                       PciIoDevice->Handle,
-                                       &PlatformOpRomBuffer,
-                                       &PlatformOpRomSize
-                                       );
-      if (!EFI_ERROR (Status)) {
-        PciIoDevice->EmbeddedRom    = FALSE;
-        PciIoDevice->RomSize        = (UINT32) PlatformOpRomSize;
-        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
-        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
-        //
-        // For OpROM read from gPciOverrideProtocol:
-        // Add the Rom Image to internal database for later PCI light enumeration
-        //
-        PciRomAddImageMapping (
+    Status = GetPlatformPciOptionRom ( Controller, PciIoDevice);
+    if (!EFI_ERROR (Status)) {
+      //
+      // For OpROM read from the PCI Platform Protocol:
+      // Add the Rom Image to internal database for later PCI light enumeration
+      //
+      PciRomAddImageMapping (
           NULL,
           PciIoDevice->PciRootBridgeIo->SegmentNumber,
           PciIoDevice->BusNumber,
@@ -294,8 +258,7 @@ RegisterPciDevice (
           PciIoDevice->FunctionNumber,
           PciIoDevice->PciIo.RomImage,
           PciIoDevice->PciIo.RomSize
-          );
-      }
+        );
     }
   }
 
@@ -597,7 +560,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 +575,82 @@ DeRegisterPciDevice (
 
 **/
 EFI_STATUS
-StartPciDevicesOnBridge (
+StartPciRootPortsOnBridge (
+  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 = StartPciRootPortsOnBridge (
+                 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 +664,6 @@ StartPciDevicesOnBridge (
   EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;
   EFI_STATUS                Status;
   LIST_ENTRY                *CurrentLink;
-  UINT64                    Supports;
 
   PciIoDevice = NULL;
   CurrentLink = RootBridge->ChildList.ForwardLink;
@@ -681,7 +718,7 @@ StartPciDevicesOnBridge (
       // If it is a PPB
       //
       if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
-        Status = StartPciDevicesOnBridge (
+        Status = RegisterPciDevicesOnBridge (
                    Controller,
                    PciIoDevice,
                    CurrentDevicePath,
@@ -689,20 +726,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 +756,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 +776,65 @@ 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) == EFI_NOT_FOUND) {
+    return Status;
+  } else {
+    if ( CheckOtherPciFeaturesPcd ()) {
+      //
+      // the late configuration of PCI features
+      //
+      Status = EnumerateOtherPciFeatures (
+                  RootBridge
+                );
+    }
+    //
+    // finally start those PCI bridge port devices only
+    //
+    return StartPciRootPortsOnBridge (
+            Controller,
+            RootBridge
+            );
+  }
+}
+
 /**
   Start to manage all the PCI devices it found previously under
   the entire host bridge.
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
index 8db1ebf8ec..0a56668380 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
@@ -1003,7 +1003,7 @@ PciHostBridgeAdjustAllocation (
     Status = RejectPciDevice (PciResNode->PciDev);
     if (Status == EFI_SUCCESS) {
       DEBUG ((
-        EFI_D_ERROR,
+        DEBUG_ERROR,
         "PciBus: [%02x|%02x|%02x] was rejected due to resource confliction.\n",
         PciResNode->PciDev->BusNumber, PciResNode->PciDev->DeviceNumber, PciResNode->PciDev->FunctionNumber
         ));
@@ -1746,7 +1746,7 @@ NotifyPhase (
 
   HostBridgeHandle  = NULL;
   RootBridgeHandle  = NULL;
-  if (gPciPlatformProtocol != NULL) {
+  if ( CheckPciPlatformProtocolInstall()) {
     //
     // Get Host Bridge Handle.
     //
@@ -1770,42 +1770,11 @@ NotifyPhase (
     //
     // Call PlatformPci::PlatformNotify() if the protocol is present.
     //
-    gPciPlatformProtocol->PlatformNotify (
-                            gPciPlatformProtocol,
-                            HostBridgeHandle,
-                            Phase,
-                            ChipsetEntry
-                            );
-  } else if (gPciOverrideProtocol != NULL){
-    //
-    // Get Host Bridge Handle.
-    //
-    PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
-
-    //
-    // Get the rootbridge Io protocol to find the host bridge handle
-    //
-    Status = gBS->HandleProtocol (
-                    RootBridgeHandle,
-                    &gEfiPciRootBridgeIoProtocolGuid,
-                    (VOID **) &PciRootBridgeIo
-                    );
-
-    if (EFI_ERROR (Status)) {
-      return EFI_NOT_FOUND;
-    }
-
-    HostBridgeHandle = PciRootBridgeIo->ParentHandle;
-
-    //
-    // Call PlatformPci::PhaseNotify() if the protocol is present.
-    //
-    gPciOverrideProtocol->PlatformNotify (
-                            gPciOverrideProtocol,
-                            HostBridgeHandle,
-                            Phase,
-                            ChipsetEntry
-                            );
+    PciPlatformNotifyPhase (
+        HostBridgeHandle,
+        Phase,
+        ChipsetEntry
+        );
   }
 
   Status = PciResAlloc->NotifyPhase (
@@ -1813,27 +1782,15 @@ NotifyPhase (
                           Phase
                           );
 
-  if (gPciPlatformProtocol != NULL) {
+  if ( CheckPciPlatformProtocolInstall()) {
     //
     // Call PlatformPci::PlatformNotify() if the protocol is present.
     //
-    gPciPlatformProtocol->PlatformNotify (
-                            gPciPlatformProtocol,
-                            HostBridgeHandle,
-                            Phase,
-                            ChipsetExit
-                            );
-
-  } else if (gPciOverrideProtocol != NULL) {
-    //
-    // Call PlatformPci::PhaseNotify() if the protocol is present.
-    //
-    gPciOverrideProtocol->PlatformNotify (
-                            gPciOverrideProtocol,
-                            HostBridgeHandle,
-                            Phase,
-                            ChipsetExit
-                            );
+    PciPlatformNotifyPhase (
+        HostBridgeHandle,
+        Phase,
+        ChipsetExit
+        );
   }
 
   return Status;
@@ -1914,31 +1871,16 @@ PreprocessController (
   RootBridgePciAddress.Bus              = Bus;
   RootBridgePciAddress.ExtendedRegister = 0;
 
-  if (gPciPlatformProtocol != NULL) {
-    //
-    // Call PlatformPci::PrepController() if the protocol is present.
-    //
-    gPciPlatformProtocol->PlatformPrepController (
-                            gPciPlatformProtocol,
-                            HostBridgeHandle,
-                            RootBridgeHandle,
-                            RootBridgePciAddress,
-                            Phase,
-                            ChipsetEntry
-                            );
-  } else if (gPciOverrideProtocol != NULL) {
-    //
-    // Call PlatformPci::PrepController() if the protocol is present.
-    //
-    gPciOverrideProtocol->PlatformPrepController (
-                            gPciOverrideProtocol,
-                            HostBridgeHandle,
-                            RootBridgeHandle,
-                            RootBridgePciAddress,
-                            Phase,
-                            ChipsetEntry
-                            );
-  }
+  //
+  // Call PlatformPci::PrepController() if the protocol is present.
+  //
+  PciPlatformPreprocessController (
+      HostBridgeHandle,
+      RootBridgeHandle,
+      RootBridgePciAddress,
+      Phase,
+      ChipsetEntry
+    );
 
   Status = PciResAlloc->PreprocessController (
                           PciResAlloc,
@@ -1947,31 +1889,16 @@ PreprocessController (
                           Phase
                           );
 
-  if (gPciPlatformProtocol != NULL) {
-    //
-    // Call PlatformPci::PrepController() if the protocol is present.
-    //
-    gPciPlatformProtocol->PlatformPrepController (
-                            gPciPlatformProtocol,
-                            HostBridgeHandle,
-                            RootBridgeHandle,
-                            RootBridgePciAddress,
-                            Phase,
-                            ChipsetExit
-                            );
-  } else if (gPciOverrideProtocol != NULL) {
-    //
-    // Call PlatformPci::PrepController() if the protocol is present.
-    //
-    gPciOverrideProtocol->PlatformPrepController (
-                            gPciOverrideProtocol,
-                            HostBridgeHandle,
-                            RootBridgeHandle,
-                            RootBridgePciAddress,
-                            Phase,
-                            ChipsetExit
-                            );
-  }
+  //
+  // Call PlatformPci::PrepController() if the protocol is present.
+  //
+  PciPlatformPreprocessController (
+      HostBridgeHandle,
+      RootBridgeHandle,
+      RootBridgePciAddress,
+      Phase,
+      ChipsetExit
+    );
 
   return EFI_SUCCESS;
 }
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
index c7eafff593..2343702154 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
@@ -230,7 +230,7 @@ PciSearchDevice (
   PciIoDevice = NULL;
 
   DEBUG ((
-    EFI_D_INFO,
+    DEBUG_INFO,
     "PciBus: Discovered %s @ [%02x|%02x|%02x]\n",
     IS_PCI_BRIDGE (Pci) ?     L"PPB" :
     IS_CARDBUS_BRIDGE (Pci) ? L"P2C" :
@@ -397,7 +397,7 @@ DumpPpbPaddingResource (
 
     if ((Type != PciBarTypeUnknown) && ((ResourceType == PciBarTypeUnknown) || (ResourceType == Type))) {
       DEBUG ((
-        EFI_D_INFO,
+        DEBUG_INFO,
         "   Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n",
         mBarTypeStr[Type], Descriptor->AddrRangeMax, Descriptor->AddrLen
         ));
@@ -424,7 +424,7 @@ DumpPciBars (
     }
 
     DEBUG ((
-      EFI_D_INFO,
+      DEBUG_INFO,
       "   BAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
       Index, mBarTypeStr[MIN (PciIoDevice->PciBar[Index].BarType, PciBarTypeMaxType)],
       PciIoDevice->PciBar[Index].Alignment, PciIoDevice->PciBar[Index].Length, PciIoDevice->PciBar[Index].Offset
@@ -437,13 +437,13 @@ DumpPciBars (
     }
 
     DEBUG ((
-      EFI_D_INFO,
+      DEBUG_INFO,
       " VFBAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
       Index, mBarTypeStr[MIN (PciIoDevice->VfPciBar[Index].BarType, PciBarTypeMaxType)],
       PciIoDevice->VfPciBar[Index].Alignment, PciIoDevice->VfPciBar[Index].Length, PciIoDevice->VfPciBar[Index].Offset
       ));
   }
-  DEBUG ((EFI_D_INFO, "\n"));
+  DEBUG ((DEBUG_INFO, "\n"));
 }
 
 /**
@@ -1903,7 +1903,7 @@ PciParseBar (
       // Fix the length to support some special 64 bit BAR
       //
       if (Value == 0) {
-        DEBUG ((EFI_D_INFO, "[PciBus]BAR probing for upper 32bit of MEM64 BAR returns 0, change to 0xFFFFFFFF.\n"));
+        DEBUG ((DEBUG_INFO, "[PciBus]BAR probing for upper 32bit of MEM64 BAR returns 0, change to 0xFFFFFFFF.\n"));
         Value = (UINT32) -1;
       } else {
         Value |= ((UINT32)(-1) << HighBitSet32 (Value));
@@ -2153,7 +2153,17 @@ CreatePciIoDevice (
              NULL
              );
   if (!EFI_ERROR (Status)) {
-    PciIoDevice->IsPciExp = TRUE;
+  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->PciExpStruct
+                );
   }
 
   if (PcdGetBool (PcdAriSupport)) {
@@ -2206,7 +2216,7 @@ CreatePciIoDevice (
                               &Data32
                               );
           DEBUG ((
-            EFI_D_INFO,
+            DEBUG_INFO,
             " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n",
             Bridge->BusNumber,
             Bridge->DeviceNumber,
@@ -2215,7 +2225,7 @@ CreatePciIoDevice (
         }
       }
 
-      DEBUG ((EFI_D_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice->AriCapabilityOffset));
+      DEBUG ((DEBUG_INFO, " ARI: CapOffset = 0x%x\n", PciIoDevice->AriCapabilityOffset));
     }
   }
 
@@ -2325,12 +2335,12 @@ CreatePciIoDevice (
       PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID (LastVF) - Bus + 1);
 
       DEBUG ((
-        EFI_D_INFO,
+        DEBUG_INFO,
         " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x; FirstVFOffset = 0x%x;\n",
         SupportedPageSize, PciIoDevice->SystemPageSize >> 12, FirstVFOffset
         ));
       DEBUG ((
-        EFI_D_INFO,
+        DEBUG_INFO,
         "         InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset = 0x%x\n",
         PciIoDevice->InitialVFs, PciIoDevice->ReservedBusNum, PciIoDevice->SrIovCapabilityOffset
         ));
@@ -2345,7 +2355,7 @@ CreatePciIoDevice (
                NULL
                );
     if (!EFI_ERROR (Status)) {
-      DEBUG ((EFI_D_INFO, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice->MrIovCapabilityOffset));
+      DEBUG ((DEBUG_INFO, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice->MrIovCapabilityOffset));
     }
   }
 
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
new file mode 100644
index 0000000000..0819da6536
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -0,0 +1,1601 @@
+/** @file
+  PCI standard feature support functions implementation for PCI Bus module..
+
+Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciFeatureSupport.h"
+
+/**
+  A gobal pointer to PRIMARY_ROOT_PORT_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
+**/
+PRIMARY_ROOT_PORT_NODE                      *mPrimaryRootPortList;
+
+/**
+  A gobal pointer to OTHER_PCI_FEATURES_CONFIGURATION_TABLE buffer all the PCI
+  Feature configuration Table nodes to pair against each of the PRIMARY_ROOT_PORT_NODE
+  buffer nodes. Each node of these is used to align all the PCI devices originating
+  from the PCI Root Port devices of a PCI Root Bridge instance
+**/
+OTHER_PCI_FEATURES_CONFIGURATION_TABLE      *mPciFeaturesConfigurationTableInstances;
+
+/**
+  A global pointer to PCI_FEATURE_CONFIGURATION_COMPLETION_LIST, which stores all
+  the PCI Root Bridge instances that are enumerated for the other PCI features,
+  like MaxPayloadSize & MaxReadReqSize; during the the Start() interface of the
+  driver binding protocol. The records pointed by this pointer would be destroyed
+  when the DXE core invokes the Stop() interface.
+**/
+PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *mPciFeaturesConfigurationCompletionList = NULL;
+
+/**
+  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
+CheckOtherPciFeaturesPcd (
+  )
+{
+  return PcdGet32 ( PcdOtherPciFeatures) ? TRUE : FALSE;
+}
+
+/**
+  Main routine to indicate whether the platform has selected the Max_Payload_Size
+  PCI feature to be configured by this driver
+
+  @retval TRUE    platform has selected the Max_Payload_Size to be configured
+          FALSE   platform has not selected this feature
+**/
+BOOLEAN
+SetupMaxPayloadSize (
+  )
+{
+  return (PcdGet32 ( PcdOtherPciFeatures) & PCI_FEATURE_SUPPORT_FLAG_MPS) ? TRUE : FALSE;
+}
+
+/**
+  Main routine to indicate whether the platform has selected the Max_Read_Req_Size
+  PCI feature to be configured by this driver
+
+  @retval TRUE    platform has selected the Max_Read_Req_Size to be configured
+          FALSE   platform has not selected this feature
+**/
+BOOLEAN
+SetupMaxReadReqSize (
+  )
+{
+  return (PcdGet32 ( PcdOtherPciFeatures) & PCI_FEATURE_SUPPORT_FLAG_MRRS) ? TRUE : FALSE;
+}
+
+/**
+  Helper routine which determines whether the given PCI Root Bridge instance
+  record already exist. This routine shall help avoid duplicate record creation
+  in case of re-enumeration of PCI configuation features.
+
+  @param  RootBridge              A pointer to the PCI_IO_DEVICE for the Root Bridge
+  @param  PciFeatureConfigRecord  A pointer to a pointer for type
+                                  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
+                                  record, Use to return the specific record.
+
+  @retval TRUE                    Record already exist
+          FALSE                   Record does not exist for the given PCI Root Bridge
+**/
+BOOLEAN
+CheckPciFeatureConfigurationRecordExist (
+  IN  PCI_IO_DEVICE                             *RootBridge,
+  OUT PCI_FEATURE_CONFIGURATION_COMPLETION_LIST **PciFeatureConfigRecord
+  )
+{
+  LIST_ENTRY                                  *Link;
+  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
+
+  if ( mPciFeaturesConfigurationCompletionList) {
+    Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
+
+    do {
+      Temp = PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK (Link);
+      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
+        *PciFeatureConfigRecord = Temp;
+        return TRUE;
+      }
+      Link = Link->ForwardLink;
+    } while (Link != &mPciFeaturesConfigurationCompletionList->RootBridgeLink);
+  }
+  //
+  // not found on the PCI feature configuration completion list
+  //
+  *PciFeatureConfigRecord = NULL;
+  return FALSE;
+}
+
+/**
+  This routine is primarily to avoid multiple configuration of PCI features
+  to the same PCI Root Bridge due to EDK2 core's ConnectController calls on
+  all the EFI handles. This routine also provide re-enumeration of the PCI
+  features on the same PCI Root Bridge based on the policy of ReEnumeratePciFeatureConfiguration
+  of the PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
+
+  @param  RootBridge              A pointer to the PCI_IO_DEVICE for the Root Bridge
+
+  @retval TRUE                    PCI Feature configuration required for the PCI
+                                  Root Bridge
+          FALSE                   PCI Feature configuration is not required to be
+                                  re-enumerated for the PCI Root Bridge
+**/
+BOOLEAN
+CheckPciFeaturesConfigurationRequired (
+  IN PCI_IO_DEVICE          *RootBridge
+  )
+{
+  LIST_ENTRY                                  *Link;
+  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
+
+  if ( mPciFeaturesConfigurationCompletionList) {
+    Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
+
+    do {
+      Temp = PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK (Link);
+      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
+        return Temp->ReEnumeratePciFeatureConfiguration;
+      }
+      Link = Link->ForwardLink;
+    } while (Link != &mPciFeaturesConfigurationCompletionList->RootBridgeLink);
+  }
+  //
+  // not found on the PCI feature configuration completion list, return as required
+  //
+  return TRUE;
+}
+
+/**
+  This routine finds the duplicate record if exist and assigns the re-enumeration
+  requirement flag, as passed as input. It creates new record for the PCI Root
+  Bridge and appends the list after updating its re-enumeration flag.
+
+  @param  RootBridge            A pointer to PCI_IO_DEVICE of the Root Bridge
+  @param  ReEnumerationRequired A BOOLEAN for recording the re-enumeration requirement
+
+  @retval EFI_SUCCESS           new record inserted into the list or updated the
+                                existing record
+          EFI_INVALID_PARAMETER Unexpected error as CheckPciFeatureConfigurationRecordExist
+                                reports as record exist but does not return its pointer
+          EFI_OUT_OF_RESOURCES  Not able to create PCI features configuratin complete
+                                record for the RootBridge
+**/
+EFI_STATUS
+AddRootBridgeInPciFeaturesConfigCompletionList (
+  IN PCI_IO_DEVICE          *RootBridge,
+  IN BOOLEAN                ReEnumerationRequired
+  )
+{
+  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
+
+  if ( CheckPciFeatureConfigurationRecordExist ( RootBridge, &Temp)) {
+    //
+    // this PCI Root Bridge record already exist; it may have been re-enumerated
+    // hence just update its enumeration required flag again to exit
+    //
+    if ( Temp) {
+      Temp->ReEnumeratePciFeatureConfiguration  = ReEnumerationRequired;
+      return EFI_SUCCESS;
+    } else {
+      //
+      // PCI feature configuration complete record reported as exist and no
+      // record pointer returned
+      //
+      return EFI_INVALID_PARAMETER;
+    }
+
+  } else {
+
+    Temp = AllocateZeroPool ( sizeof ( PCI_FEATURE_CONFIGURATION_COMPLETION_LIST));
+    if ( !Temp) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    Temp->Signature                           = PCI_FEATURE_CONFIGURATION_SIGNATURE;
+    Temp->RootBridgeHandle                    = RootBridge->Handle;
+    Temp->ReEnumeratePciFeatureConfiguration  = ReEnumerationRequired;
+    if ( mPciFeaturesConfigurationCompletionList) {
+      InsertTailList ( &mPciFeaturesConfigurationCompletionList->RootBridgeLink,
+                       &Temp->RootBridgeLink);
+    } else {
+      //
+      // init the very first node of the Root Bridge
+      //
+      mPciFeaturesConfigurationCompletionList = Temp;
+      InitializeListHead ( &mPciFeaturesConfigurationCompletionList->RootBridgeLink);
+    }
+  }
+  return EFI_SUCCESS;
+}
+
+/**
+  Free up memory alloted for the primary physical PCI Root ports of the PCI Root
+  Bridge instance. Free up all the nodes of type PRIMARY_ROOT_PORT_NODE.
+**/
+VOID
+DestroyPrimaryRootPortNodes ()
+{
+  LIST_ENTRY                *Link;
+  PRIMARY_ROOT_PORT_NODE    *Temp;
+
+  if ( mPrimaryRootPortList) {
+    Link = &mPrimaryRootPortList->NeighborRootPort;
+
+    if ( IsListEmpty ( Link)) {
+      FreePool ( mPrimaryRootPortList);
+    } else {
+      do {
+        if ( Link->ForwardLink != &mPrimaryRootPortList->NeighborRootPort) {
+          Link = Link->ForwardLink;
+        }
+        Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
+        Link = RemoveEntryList ( Link);
+        FreePool ( Temp);
+      } while ( !IsListEmpty ( Link));
+      FreePool ( mPrimaryRootPortList);
+    }
+    mPrimaryRootPortList = NULL;
+  }
+}
+
+/**
+  Free up the memory allocated for temporarily maintaining the PCI feature
+  configuration table for all the nodes of the primary PCI Root port.
+  Free up memory alloted for OTHER_PCI_FEATURES_CONFIGURATION_TABLE.
+**/
+VOID
+ErasePciFeaturesConfigurationTable (
+  )
+{
+  if ( mPciFeaturesConfigurationTableInstances) {
+    FreePool ( mPciFeaturesConfigurationTableInstances);
+  }
+  mPciFeaturesConfigurationTableInstances = NULL;
+}
+
+/**
+  Routine meant for initializing any global variables used. It primarily cleans
+  up the internal data structure memory allocated for the previous PCI Root Bridge
+  instance. This should be the first routine to call for any virtual PCI Root
+  Bridge instance.
+**/
+VOID
+SetupPciFeaturesConfigurationDefaults ()
+{
+  //
+  // delete the primary root port list
+  //
+  if (mPrimaryRootPortList) {
+    DestroyPrimaryRootPortNodes ();
+  }
+
+  if ( mPciFeaturesConfigurationTableInstances) {
+    ErasePciFeaturesConfigurationTable ();
+  }
+}
+
+/**
+  Helper routine to determine whether the PCI device is a physical root port
+  recorded in the list.
+
+  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
+
+  @retval TRUE                            The PCI device instance is a primary
+                                          primary physical PCI Root Port
+          FALSE                           Not a primary physical PCI Root port
+**/
+BOOLEAN
+CheckRootBridgePrimaryPort (
+  IN PCI_IO_DEVICE          *PciDevice
+  )
+{
+  LIST_ENTRY                *Link;
+  PRIMARY_ROOT_PORT_NODE    *Temp;
+
+  if ( !mPrimaryRootPortList) {
+    return FALSE;
+  }
+  Link = &mPrimaryRootPortList->NeighborRootPort;
+  do {
+    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
+    if ( Temp->RootBridgeHandle == PciDevice->Parent->Handle
+        && Temp->RootPortHandle == PciDevice->Handle) {
+      //
+      // the given PCI device is the primary root port of the Root Bridge controller
+      //
+      return TRUE;
+    }
+    Link = Link->ForwardLink;
+  } while ( Link != &mPrimaryRootPortList->NeighborRootPort);
+  //
+  // the given PCI device is not the primary root port of the Bridge controller
+  //
+  return FALSE;
+}
+
+/**
+  Main routine to determine the child PCI devices of a physical 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
+                                          OTHER_PCI_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 PCU 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_NOT_FOUND                   the PCI feature configuration table does
+                                          not exist as the PCI physical Bridge device
+                                          is not found for this device's parent
+                                          Root Bridge instance
+**/
+EFI_STATUS
+GetPciFeaturesConfigurationTable (
+  IN  PCI_IO_DEVICE                           *PciDevice,
+  OUT OTHER_PCI_FEATURES_CONFIGURATION_TABLE  **PciFeaturesConfigTable
+  )
+{
+  LIST_ENTRY                *Link;
+  PRIMARY_ROOT_PORT_NODE    *Temp;
+
+  if ( !mPrimaryRootPortList) {
+    *PciFeaturesConfigTable = NULL;
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // The PCI features configuration table is not built for RCiEP, return NULL
+  //
+  if ( PciDevice->PciExpStruct.Capability.Bits.DevicePortType == \
+        PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT) {
+    *PciFeaturesConfigTable = NULL;
+    return EFI_SUCCESS;
+  }
+
+  Link = &mPrimaryRootPortList->NeighborRootPort;
+  do {
+    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
+    if ( Temp->RootBridgeHandle == PciDevice->Parent->Handle
+        && Temp->RootPortHandle == PciDevice->Handle) {
+      //
+      // the given PCI device is the primary root port of the Root Bridge controller
+      //
+      *PciFeaturesConfigTable = Temp->OtherPciFeaturesConfigurationTable;
+      return EFI_SUCCESS;
+    } else {
+      //
+      // check this PCI device belongs to the primary root port of the root bridge
+      //
+      if ( PciDevice->BusNumber >= Temp->SecondaryBusStart
+          && PciDevice->BusNumber <= Temp->SecondaryBusEnd) {
+        *PciFeaturesConfigTable = Temp->OtherPciFeaturesConfigurationTable;
+        return EFI_SUCCESS;
+      }
+    }
+    Link = Link->ForwardLink;
+  } while ( Link != &mPrimaryRootPortList->NeighborRootPort);
+  //
+  // the PCI device must be RCiEP, does not belong to any primary root port
+  //
+  *PciFeaturesConfigTable = NULL;
+  return EFI_SUCCESS;
+}
+
+/**
+  The helper routine to retrieve the PCI bus numbers from the PCI Bridge or Root
+  port device. Assumes the input PCI device has the PCI Type 1 configuration header.
+
+  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
+  @param  PrimaryBusNumber                A pointer to return the PCI Priamry
+                                          Bus number.
+  @param  SecondaryBusNumber              A pointer to return the PCI Secondary
+                                          Bus number.
+  @param  SubordinateBusNumber            A pointer to return the PCI Subordinate
+                                          Bus number.
+
+  @retval EFI_SUCCESS           The data was read from 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 device.
+  @retval EFI_INVALID_PARAMETER input parameters provided to the read operation were invalid.
+**/
+EFI_STATUS
+GetPciRootPortBusAssigned (
+  IN  PCI_IO_DEVICE                           *PciDevice,
+  OUT UINT8                                   *PrimaryBusNumber,
+  OUT UINT8                                   *SecondaryBusNumber,
+  OUT UINT8                                   *SubordinateBusNumber
+  )
+{
+  EFI_STATUS                                  Status;
+  UINT32                                      RootPortBusAssigned;
+
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint32,
+                                  PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET,
+                                  1,
+                                  &RootPortBusAssigned
+                                );
+  if ( !EFI_ERROR(Status)) {
+    if ( PrimaryBusNumber) {
+      *PrimaryBusNumber = (UINT8) (0xFF & RootPortBusAssigned);
+    }
+    if ( SecondaryBusNumber) {
+      *SecondaryBusNumber = (UINT8)(0xFF & (RootPortBusAssigned >> 8));
+    }
+    if ( SubordinateBusNumber) {
+      *SubordinateBusNumber = (UINT8)(0xFF & (RootPortBusAssigned >> 16));
+    }
+  }
+  return Status;
+}
+
+/**
+  This routine determines the existance of the child PCI device for the given
+  PCI Root / Bridge Port device. Always assumes the input PCI device is the bridge
+  or PCI-PCI Bridge device. This routine should not be used with PCI endpoint device.
+
+  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
+
+  @retval TRUE                            child device exist
+          FALSE                           no child device
+**/
+BOOLEAN
+IsPciRootPortEmpty (
+  IN  PCI_IO_DEVICE                           *PciDevice
+  )
+{
+  UINT8                                       SecBus,
+                                              SubBus;
+  EFI_STATUS                                  Status;
+  LIST_ENTRY                                  *Link;
+  PCI_IO_DEVICE                               *NextPciDevice;
+
+  //
+  // check secondary & suboridinate bus numbers for its endpoint device
+  // existance
+  //
+  Status = GetPciRootPortBusAssigned ( PciDevice, NULL, &SecBus, &SubBus);
+  if ( !EFI_ERROR( Status)) {
+    Link = PciDevice->ChildList.ForwardLink;
+    if ( IsListEmpty ( Link)) {
+      //
+      // return as PCI Root port empty
+      //
+      DEBUG (( DEBUG_INFO, "RP empty,"));
+      return TRUE;
+    }
+    do {
+      NextPciDevice = PCI_IO_DEVICE_FROM_LINK ( Link);
+      DEBUG (( DEBUG_INFO, "dev@%x", NextPciDevice->BusNumber));
+
+      if ( NextPciDevice->BusNumber >= SecBus
+          && NextPciDevice->BusNumber <= SubBus) {
+
+        return FALSE;
+      }
+
+      Link = Link->ForwardLink;
+    } while ( Link != &PciDevice->ChildList);
+  } else {
+    SecBus = SubBus = 0;
+    DEBUG (( DEBUG_ERROR, "unable to retrieve root port's bus range assigned!!!"));
+  }
+
+  //
+  // return as PCI Root port empty
+  //
+  return TRUE;
+}
+
+/**
+  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 PciConfigPhase                 for the PCI feature configuration phases:
+                                        PciFeatureGetDevicePolicy & PciFeatureSetupPhase
+  @param PciFeaturesConfigurationTable  pointer to OTHER_PCI_FEATURES_CONFIGURATION_TABLE
+
+  @retval EFI_SUCCESS                   processing of PCI feature Max_Payload_Size
+                                        is successful.
+**/
+EFI_STATUS
+ProcessMaxPayloadSize (
+  IN  PCI_IO_DEVICE                           *PciDevice,
+  IN  PCI_FEATURE_CONFIGURATION_PHASE         PciConfigPhase,
+  IN  OTHER_PCI_FEATURES_CONFIGURATION_TABLE  *PciFeaturesConfigurationTable
+  )
+{
+  PCI_REG_PCIE_DEVICE_CAPABILITY          PciDeviceCap;
+  UINT8                                   MpsValue;
+
+
+  PciDeviceCap.Uint32 = PciDevice->PciExpStruct.DeviceCapability.Uint32;
+
+  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
+    if ( SetupMpsAsPerDeviceCapability ( PciDevice->SetupMPS))
+    {
+      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 ( IsPciRootPortEmpty ( PciDevice)) {
+          MpsValue = PCIE_MAX_PAYLOAD_SIZE_128B;
+          DEBUG (( DEBUG_INFO, "(reset RP MPS to min.)"));
+        }
+      }
+    } else {
+      MpsValue = TranslateMpsSetupValueToPci ( PciDevice->SetupMPS);
+    }
+    //
+    // discard device policy override request if greater than PCI device capability
+    //
+    PciDevice->SetupMPS = MIN( (UINT8)PciDeviceCap.Bits.MaxPayloadSize, MpsValue);
+  }
+
+  //
+  // align the MPS of the tree to the HCF with this device
+  //
+  if ( PciFeaturesConfigurationTable) {
+    MpsValue = PciFeaturesConfigurationTable->Max_Payload_Size;
+
+    MpsValue = MIN ( PciDevice->SetupMPS, MpsValue);
+    PciDevice->SetupMPS = MIN ( PciDevice->SetupMPS, MpsValue);
+
+    if ( MpsValue != PciFeaturesConfigurationTable->Max_Payload_Size) {
+      DEBUG (( DEBUG_INFO, "reset MPS of the tree to %d,", MpsValue));
+      PciFeaturesConfigurationTable->Max_Payload_Size = MpsValue;
+    }
+  }
+
+  DEBUG (( DEBUG_INFO,
+      "Max_Payload_Size: %d [DevCap:%d],",
+      PciDevice->SetupMPS, PciDeviceCap.Bits.MaxPayloadSize
+  ));
+  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 PciConfigPhase                 for the PCI feature configuration phases:
+                                        PciFeatureGetDevicePolicy & PciFeatureSetupPhase
+  @param PciFeaturesConfigurationTable  pointer to OTHER_PCI_FEATURES_CONFIGURATION_TABLE
+
+  @retval EFI_SUCCESS                   processing of PCI feature Max_Read_Req_Size
+                                        is successful.
+**/
+EFI_STATUS
+ProcessMaxReadReqSize (
+  IN  PCI_IO_DEVICE                           *PciDevice,
+  IN  PCI_FEATURE_CONFIGURATION_PHASE         PciConfigPhase,
+  IN  OTHER_PCI_FEATURES_CONFIGURATION_TABLE  *PciFeaturesConfigurationTable
+  )
+{
+  PCI_REG_PCIE_DEVICE_CAPABILITY  PciDeviceCap;
+  UINT8                           MrrsValue;
+
+  PciDeviceCap.Uint32 = PciDevice->PciExpStruct.DeviceCapability.Uint32;
+
+  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
+    if ( SetupMrrsAsPerDeviceCapability ( PciDevice->SetupMRRS))
+    {
+      //
+      // 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 ( SetupMaxPayloadSize()) {
+        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 = TranslateMrrsSetupValueToPci ( PciDevice->SetupMRRS);
+      //
+      // align this device's Max_Read_Request_Size value to the entire PCI tree
+      //
+      if ( PciFeaturesConfigurationTable) {
+        if ( !PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size) {
+          PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size = TRUE;
+          PciFeaturesConfigurationTable->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,
+                        PciFeaturesConfigurationTable->Max_Read_Request_Size
+                        );
+          PciFeaturesConfigurationTable->Max_Read_Request_Size = MrrsValue;
+        }
+      }
+    }
+    //
+    // align this device's Max_Read_Request_Size to derived configuration value
+    //
+    PciDevice->SetupMRRS = MrrsValue;
+
+  }
+
+  //
+  // 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 ( PciFeaturesConfigurationTable) {
+    if ( PciFeaturesConfigurationTable->Lock_Max_Read_Request_Size) {
+      PciDevice->SetupMRRS = PciFeaturesConfigurationTable->Max_Read_Request_Size;
+    } else {
+      if ( SetupMaxPayloadSize()) {
+        PciDevice->SetupMRRS = PciDevice->SetupMPS;
+      } else {
+        PciDevice->SetupMRRS = MIN (
+                                PciDevice->SetupMRRS,
+                                PciFeaturesConfigurationTable->Max_Read_Request_Size
+                                );
+      }
+      PciFeaturesConfigurationTable->Max_Read_Request_Size = PciDevice->SetupMRRS;
+    }
+  }
+  DEBUG (( DEBUG_INFO, "Max_Read_Request_Size: %d\n", PciDevice->SetupMRRS));
+
+  return EFI_SUCCESS;
+}
+
+/**
+  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
+OverrideMaxPayloadSize (
+  IN PCI_IO_DEVICE          *PciDevice
+  )
+{
+  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
+  UINT32                      Offset;
+  EFI_STATUS                  Status;
+
+  PcieDev.Uint16 = 0;
+  Offset = PciDevice->PciExpressCapabilityOffset +
+               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint16,
+                                  Offset,
+                                  1,
+                                  &PcieDev.Uint16
+                                );
+  if ( EFI_ERROR(Status)){
+    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) read error!",
+        Offset
+    ));
+    return Status;
+  }
+  if ( PcieDev.Bits.MaxPayloadSize != PciDevice->SetupMPS) {
+    PcieDev.Bits.MaxPayloadSize = PciDevice->SetupMPS;
+    DEBUG (( DEBUG_INFO, "Max_Payload_Size=%d,", PciDevice->SetupMPS));
+
+    Status = PciDevice->PciIo.Pci.Write (
+                                    &PciDevice->PciIo,
+                                    EfiPciIoWidthUint16,
+                                    Offset,
+                                    1,
+                                    &PcieDev.Uint16
+                                  );
+    if ( !EFI_ERROR(Status)) {
+      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
+    } else {
+      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) write error!",
+          Offset
+      ));
+    }
+  } else {
+    DEBUG (( DEBUG_INFO, "No write of Max_Payload_Size=%d,", PciDevice->SetupMPS));
+  }
+
+  return Status;
+}
+
+/**
+  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 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
+OverrideMaxReadReqSize (
+  IN PCI_IO_DEVICE          *PciDevice
+  )
+{
+  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
+  UINT32                      Offset;
+  EFI_STATUS                  Status;
+
+  PcieDev.Uint16 = 0;
+  Offset = PciDevice->PciExpressCapabilityOffset +
+               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint16,
+                                  Offset,
+                                  1,
+                                  &PcieDev.Uint16
+                                );
+  if ( EFI_ERROR(Status)){
+    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) read error!",
+        Offset
+    ));
+    return Status;
+  }
+  if ( PcieDev.Bits.MaxReadRequestSize != PciDevice->SetupMRRS) {
+    PcieDev.Bits.MaxReadRequestSize = PciDevice->SetupMRRS;
+    DEBUG (( DEBUG_INFO, "Max_Read_Request_Size: %d\n", PciDevice->SetupMRRS));
+
+    Status = PciDevice->PciIo.Pci.Write (
+                                    &PciDevice->PciIo,
+                                    EfiPciIoWidthUint16,
+                                    Offset,
+                                    1,
+                                    &PcieDev.Uint16
+                                  );
+    if ( !EFI_ERROR(Status)) {
+      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
+    } else {
+      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) write error!",
+          Offset
+      ));
+    }
+  } else {
+    DEBUG (( DEBUG_INFO, "No write of Max_Read_Request_Size=%d\n", PciDevice->SetupMRRS));
+  }
+
+  return Status;
+}
+
+/**
+  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;
+  }
+}
+
+/**
+   Process each PCI device as per the pltaform and device-specific policy.
+
+  @param RootBridge             A pointer to the PCI_IO_DEVICE.
+
+  @retval EFI_SUCCESS           processing each PCI feature as per policy defined
+                                was successful.
+ **/
+EFI_STATUS
+SetupDevicePciFeatures (
+  IN  PCI_IO_DEVICE                   *PciDevice,
+  IN  PCI_FEATURE_CONFIGURATION_PHASE PciConfigPhase
+  )
+{
+  EFI_STATUS                              Status;
+  PCI_REG_PCIE_CAPABILITY                 PcieCap;
+  OTHER_PCI_FEATURES_CONFIGURATION_TABLE  *OtherPciFeaturesConfigTable;
+
+  PcieCap.Uint16 = PciDevice->PciExpStruct.Capability.Uint16;
+  DumpDevicePortType ( (UINT8)PcieCap.Bits.DevicePortType);
+
+  OtherPciFeaturesConfigTable = NULL;
+  Status = GetPciFeaturesConfigurationTable ( PciDevice, &OtherPciFeaturesConfigTable);
+  if ( EFI_ERROR( Status)) {
+    DEBUG ((
+        EFI_D_WARN, "No primary root port found in these root bridge nodes!\n"
+    ));
+  } else if ( !OtherPciFeaturesConfigTable) {
+    DEBUG ((
+        DEBUG_INFO, "No PCI features config. table for this device!\n"
+    ));
+  } else {
+    DEBUG ((
+        DEBUG_INFO, "using PCI features config. table ID: %d\n",
+        OtherPciFeaturesConfigTable->ID
+    ));
+  }
+
+  if ( PciConfigPhase == PciFeatureGetDevicePolicy) {
+    Status = GetPciDevicePlatformPolicy ( PciDevice);
+    if ( EFI_ERROR(Status)) {
+      DEBUG ((
+          DEBUG_ERROR, "Error in obtaining PCI device policy!!!\n"
+      ));
+    }
+  }
+
+  if ( SetupMaxPayloadSize ()) {
+    Status = ProcessMaxPayloadSize (
+              PciDevice,
+              PciConfigPhase,
+              OtherPciFeaturesConfigTable
+              );
+  }
+  //
+  // implementation specific rule:- the MRRS of any PCI device should be processed
+  // only after the MPS is processed for that device
+  //
+  if ( SetupMaxReadReqSize ()) {
+    Status = ProcessMaxReadReqSize (
+              PciDevice,
+              PciConfigPhase,
+              OtherPciFeaturesConfigTable
+              );
+  }
+  return Status;
+}
+
+/**
+  Traverse all the nodes from the root bridge or PCI-PCI bridge instance, to
+  configure the PCI features as per the device-specific platform policy, and
+  as per the 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
+SetupPciFeatures (
+  IN  PCI_IO_DEVICE                   *RootBridge,
+  IN  PCI_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 (IS_PCI_BRIDGE (&Device->Pci)) {
+      DEBUG ((
+          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
+          Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+      ));
+      if (Device->IsPciExp) {
+        Status = SetupDevicePciFeatures ( 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
+        //
+
+      }
+
+      SetupPciFeatures ( Device, PciConfigPhase);
+    } else {
+      DEBUG ((
+          DEBUG_INFO, "::Device [%02x|%02x|%02x] -",
+          Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+      ));
+      if (Device->IsPciExp) {
+
+        Status = SetupDevicePciFeatures ( 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;
+}
+
+/**
+  Program the PCI device, to override the PCI features as per the policy,
+  resolved from previous traverse.
+
+  @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
+ProgramDevicePciFeatures (
+  IN PCI_IO_DEVICE          *PciDevice
+  )
+{
+  EFI_STATUS           Status;
+
+  if ( SetupMaxPayloadSize ()) {
+    Status = OverrideMaxPayloadSize (PciDevice);
+  }
+  if ( SetupMaxReadReqSize ()) {
+    Status = OverrideMaxReadReqSize (PciDevice);
+  }
+  return Status;
+}
+
+/**
+  Program all the nodes of the specified root bridge or PCI-PCI Bridge, to
+  override the 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
+ProgramPciFeatures (
+  IN PCI_IO_DEVICE          *RootBridge
+  )
+{
+  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 (IS_PCI_BRIDGE (&Device->Pci)) {
+      DEBUG ((
+          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
+          Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+      ));
+      if (Device->IsPciExp) {
+        DEBUG (( DEBUG_INFO, "ready to override!\n"));
+
+        Status = ProgramDevicePciFeatures ( Device);
+      } else {
+        DEBUG (( DEBUG_INFO, "skipped!\n"));
+        //
+        // PCI Bridge which does not have PCI Express Capability structure
+        // cannot process this kind of PCI Bridge device
+        //
+
+      }
+
+      Status = ProgramPciFeatures ( Device);
+    } else {
+      DEBUG ((
+          DEBUG_INFO, "::Device [%02x|%02x|%02x] -",
+          Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+      ));
+      if (Device->IsPciExp) {
+        DEBUG (( DEBUG_INFO, "ready to override!\n"));
+
+        Status = ProgramDevicePciFeatures ( Device);
+      } else {
+        DEBUG (( DEBUG_INFO, "skipped!\n"));
+        //
+        // PCI Device which does not have PCI Express Capability structure
+        // cannot process this kind of PCI device
+        //
+      }
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Create a node of type PRIMARY_ROOT_PORT_NODE for the given PCI device, and
+  assigns EFI handles of its Root Bridge and its own, along with its PCI Bus
+  range for the secondary and subordinate bus range.
+
+  @param  RootBridge          A pointer to the PCI_IO_DEVICE for its PCI Root Bridge
+  @param  Device              A pointer to the PCI_IO_DEVICE for the PCI controller
+  @param  RootPortSecBus      PCI controller's Secondary Bus number
+  @param  RootPortSubBus      PCI controller's Subordinate Bus number
+  @param  PrimaryRootPortNode A pointer to the PRIMARY_ROOT_PORT_NODE to return
+                              the newly created node for the PCI controller. In
+                              case of error nothing is return in this.
+
+  @retval EFI_SUCCESS           new node of PRIMARY_ROOT_PORT_NODE is returned for
+                                the PCI controller
+          EFI_OUT_OF_RESOURCES  unable to create the node for the PCI controller
+          EFI_INVALID_PARAMETER unable to store the node as the input buffer is
+                                not empty (*PrimaryRootPortNode)
+**/
+EFI_STATUS
+CreatePrimaryPciRootPortNode (
+  IN  PCI_IO_DEVICE           *RootBridge,
+  IN  PCI_IO_DEVICE           *Device,
+  IN  UINT8                   RootPortSecBus,
+  IN  UINT8                   RootPortSubBus,
+  OUT PRIMARY_ROOT_PORT_NODE  **PrimaryRootPortNode
+  )
+{
+  PRIMARY_ROOT_PORT_NODE      *RootPortNode = NULL;
+
+  if ( !*PrimaryRootPortNode) {
+    RootPortNode                    = AllocateZeroPool ( sizeof (PRIMARY_ROOT_PORT_NODE));
+    if ( RootPortNode == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    RootPortNode->Signature         = PCI_ROOT_PORT_SIGNATURE;
+    RootPortNode->RootBridgeHandle  = RootBridge->Handle;
+    RootPortNode->RootPortHandle    = Device->Handle;
+    RootPortNode->SecondaryBusStart = RootPortSecBus;
+    RootPortNode->SecondaryBusEnd   = RootPortSubBus;
+    InitializeListHead ( &RootPortNode->NeighborRootPort);
+    *PrimaryRootPortNode = RootPortNode;
+    return EFI_SUCCESS;
+  } else {
+    return EFI_INVALID_PARAMETER;
+  }
+}
+
+/**
+  Checks to report whether the input PCI controller's secondary / subordinate
+  bus numbers are within the recorded list of other PCI controllers (root ports).
+
+  @param  RootPortNode      A pointer to the first node of PRIMARY_ROOT_PORT_NODE
+  @param  RootPortSecBus    PCI secondary bus number of the PCI controller found
+  @param  RootPortSubBus    PCI subordinate bus number of the PCI Root Port found
+
+  @retval TRUE              A child PCI Root port found
+          FALSE             A new PCI controller found
+**/
+BOOLEAN
+CheckChildRootPort (
+  IN      PRIMARY_ROOT_PORT_NODE  *RootPortNode,
+  IN      UINT8                   RootPortSecBus,
+  IN      UINT8                   RootPortSubBus
+)
+{
+  LIST_ENTRY              *Link;
+  PRIMARY_ROOT_PORT_NODE  *Temp;
+
+  if ( !RootPortNode) {
+    return FALSE;
+  }
+  Link = &RootPortNode->NeighborRootPort;
+  do {
+    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
+    if ( RootPortSecBus >= Temp->SecondaryBusStart
+        && RootPortSubBus <= Temp->SecondaryBusEnd) {
+      //
+      // given root port's secondary & subordinate within its primary ports
+      // hence return as child port
+      //
+      return TRUE;
+    }
+    Link = Link->ForwardLink;
+  } while (Link != &RootPortNode->NeighborRootPort);
+  //
+  // the given root port's secondary / subordinate bus numbers do not belong to
+  // any existing primary root port's bus range hence consider another primary
+  // root port of the root bridge controller
+  //
+  return FALSE;
+}
+
+/**
+  Create the vector of PCI Feature configuration table as per the number of
+  the PCI Root Ports given, assigns default value to the PCI features supported
+  and assign its address to the global variable "mPciFeaturesConfigurationTableInstances".
+
+  @param  NumberOfRootPorts   An input arguement of UINTN to indicate number of
+                              primary PCI physical Root Bridge devices found
+
+  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store PCI feature
+                                configuration table for all the physical PCI root
+                                ports given
+          EFI_SUCCESS           PCI Feature COnfiguration table created for all
+                                the PCI Rooot ports reported
+ */
+EFI_STATUS
+CreatePciFeaturesConfigurationTableInstances (
+  IN  UINTN NumberOfRootPorts
+  )
+{
+  OTHER_PCI_FEATURES_CONFIGURATION_TABLE   *PciRootBridgePortFeatures = NULL;
+  UINTN                                     Instances;
+
+  PciRootBridgePortFeatures = AllocateZeroPool (
+                                sizeof ( OTHER_PCI_FEATURES_CONFIGURATION_TABLE) * NumberOfRootPorts
+                                );
+  if ( !PciRootBridgePortFeatures) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  for ( Instances = 0; Instances < NumberOfRootPorts; Instances++) {
+    PciRootBridgePortFeatures [Instances].ID                    = Instances + 1;
+    PciRootBridgePortFeatures [Instances].Max_Payload_Size      = PCIE_MAX_PAYLOAD_SIZE_4096B;
+    PciRootBridgePortFeatures [Instances].Max_Read_Request_Size = PCIE_MAX_READ_REQ_SIZE_4096B;
+    PciRootBridgePortFeatures [Instances].Lock_Max_Read_Request_Size = FALSE;
+  }
+  mPciFeaturesConfigurationTableInstances = PciRootBridgePortFeatures;
+  return EFI_SUCCESS;
+}
+
+/**
+  This routine pairs the each PCI Root Port node with one of the PCI Feature
+  Configuration Table node. Each physical PCI Root Port has its own PCI feature
+  configuration table which will used for aligning all its downstream components.
+
+  @param  NumberOfRootPorts     inputs the number of physical PCI root ports
+                                found on the Root bridge instance
+
+  @retval EFI_INVALID_PARAMETER if the primary PCI root ports list is vacant when
+                                there is one or more PCI Root port indicated as per
+                                input parameter
+          EFI_UNSUPPORTED       The PCI Root Port nodes not paired equally with
+                                the PCI Configuration Table nodes
+          EFI_SUCCESS           each PCI feature configuration node is paired equally
+                                with each PCI Root port in the list
+**/
+EFI_STATUS
+AssignPciFeaturesConfigurationTable (
+  IN  UINTN NumberOfRootPorts
+  )
+{
+  UINTN                       Instances;
+  LIST_ENTRY                  *Link;
+  PRIMARY_ROOT_PORT_NODE      *Temp;
+
+  if ( !mPrimaryRootPortList
+      && NumberOfRootPorts) {
+    DEBUG ((
+        DEBUG_ERROR,
+        "Critical error! no internal table setup for %d PCI Root ports \n",
+        NumberOfRootPorts
+    ));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if ( NumberOfRootPorts) {
+    Link = &mPrimaryRootPortList->NeighborRootPort;
+    for ( Instances = 0
+        ; (Instances < NumberOfRootPorts)
+        ; Instances++
+    ) {
+      Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK ( Link);
+      Temp->OtherPciFeaturesConfigurationTable = &mPciFeaturesConfigurationTableInstances [Instances];
+      DEBUG ((
+          DEBUG_INFO,
+          "Assigned to %dth primary root port\n",
+          Instances
+      ));
+
+      Link = Link->ForwardLink;
+    }
+    if ( Link != &mPrimaryRootPortList->NeighborRootPort) {
+      DEBUG ((
+          DEBUG_ERROR,
+          "Error!! PCI Root Port list is not properly matched with Config., Table list \n"
+      ));
+      return EFI_UNSUPPORTED;
+    }
+  }
+  return  EFI_SUCCESS;
+}
+
+/**
+  Prepare each PCI Controller (Root Port) with its own PCI Feature configuration
+  table node that can be used for tracking to align all PCI nodes in its hierarchy.
+
+  @param  PrimaryRootPorts      A pointer to PRIMARY_ROOT_PORT_NODE
+  @param  NumberOfRootPorts     Total number of pysical primary PCI Root ports
+
+  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store PCI feature
+                                configuration table for all the physical PCI root
+                                ports given
+          EFI_INVALID_PARAMETER if the primary PCI root ports list is vacant when
+                                there is one or more PCI Root port indicated as per
+                                input parameter
+          EFI_UNSUPPORTED       The PCI Root Port nodes not paired equally with
+                                the PCI Configuration Table nodes
+          EFI_SUCCESS           each PCI feature configuration node is paired equally
+                                with each PCI Root port in the list
+**/
+EFI_STATUS
+PreparePciControllerConfigurationTable (
+  IN  PRIMARY_ROOT_PORT_NODE    *PrimaryRootPorts,
+  IN  UINTN                     NumberOfRootPorts
+  )
+{
+  EFI_STATUS                    Status;
+
+  mPrimaryRootPortList = PrimaryRootPorts;
+  DEBUG ((
+      DEBUG_INFO, "Number of primary Root Ports found on this bridge = %d\n",
+      NumberOfRootPorts
+  ));
+
+  Status = CreatePciFeaturesConfigurationTableInstances ( NumberOfRootPorts);
+  if ( EFI_ERROR(Status)) {
+    DEBUG ((
+        DEBUG_ERROR, "Unexpected memory node creation error for PCI features!\n"
+    ));
+  } else {
+    //
+    // align the primary root port nodes list with the PCI Feature configuration
+    // table. Note that the PCI Feature configuration table is not maintain for
+    // the RCiEP devices
+    //
+    Status = AssignPciFeaturesConfigurationTable ( NumberOfRootPorts);
+  }
+  return Status;
+}
+
+/**
+  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
+RecordPciRootPortBridges (
+  IN  PCI_IO_DEVICE           *RootBridge
+  )
+{
+  EFI_STATUS              Status = EFI_NOT_FOUND;
+  LIST_ENTRY              *Link;
+  PCI_IO_DEVICE           *Device;
+  UINTN                   NumberOfRootPorts;
+  PRIMARY_ROOT_PORT_NODE  *PrimaryRootPorts,
+                          *TempNode;
+  UINT8                   RootPortSecBus,
+                          RootPortSubBus;
+
+  DEBUG ((
+      DEBUG_INFO, "<<********** RecordPciRootPortBridges -start *************>>\n"
+  ));
+  NumberOfRootPorts = 0;
+  PrimaryRootPorts = NULL;
+  for ( Link = RootBridge->ChildList.ForwardLink
+      ; Link != &RootBridge->ChildList
+      ; Link = Link->ForwardLink
+  ) {
+    Device = PCI_IO_DEVICE_FROM_LINK (Link);
+    if (IS_PCI_BRIDGE (&Device->Pci)) {
+      Status = GetPciRootPortBusAssigned (
+                  Device,
+                  NULL,
+                  &RootPortSecBus,
+                  &RootPortSubBus
+                  );
+      if ( !EFI_ERROR(Status)) {
+        DEBUG ((
+            DEBUG_INFO, "::Device [%02x|%02x|%02x] - SecBus=0x%x, SubBus=0x%x\n",
+            Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber,
+            RootPortSecBus, RootPortSubBus
+        ));
+      } else {
+        DEBUG ((
+            DEBUG_ERROR, "Unexpected read error [0x%lx]::Device [%02x|%02x|%02x]\n",
+            Status, Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+        ));
+        RootPortSecBus = RootPortSubBus = 0;
+        continue;
+      }
+
+      if ( !PrimaryRootPorts) {
+        NumberOfRootPorts++;
+        Status = CreatePrimaryPciRootPortNode (
+                    RootBridge,
+                    Device,
+                    RootPortSecBus,
+                    RootPortSubBus,
+                    &PrimaryRootPorts
+                    );
+        if ( EFI_ERROR(Status)) {
+          //
+          // abort mission to scan for all primary roots ports of a bridge
+          // controller if error encountered for very first PCI primary root port
+          //
+          DEBUG ((
+              DEBUG_ERROR, "Unexpected node creation error [0x%lx]::Device [%02x|%02x|%02x]\n",
+              Status, Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+          ));
+          return Status;
+        }
+        DEBUG ((
+            DEBUG_INFO, "first primary root port found::Device [%02x|%02x|%02x]\n",
+            Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+        ));
+      } else {
+        if ( !CheckChildRootPort ( PrimaryRootPorts, RootPortSecBus, RootPortSubBus)) {
+          NumberOfRootPorts++;
+          TempNode = NULL;
+          Status = CreatePrimaryPciRootPortNode (
+                      RootBridge,
+                      Device,
+                      RootPortSecBus,
+                      RootPortSubBus,
+                      &TempNode
+                      );
+          if ( !EFI_ERROR(Status)) {
+            //
+            // another primary root port found on the same bridge controller
+            // insert in the node list
+            //
+            InsertTailList ( &PrimaryRootPorts->NeighborRootPort, &TempNode->NeighborRootPort);
+            DEBUG ((
+                DEBUG_INFO, "next primary root port found::Device [%02x|%02x|%02x]\n",
+                Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+            ));
+          } else {
+            DEBUG ((
+                DEBUG_ERROR, "Unexpected node creation error [0x%lx]::Device [%02x|%02x|%02x]\n",
+                Status, Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+            ));
+          }
+        }
+      }
+    }
+  }
+  //
+  // prepare the PCI root port and its feature configuration table list
+  //
+  if ( NumberOfRootPorts) {
+    Status = PreparePciControllerConfigurationTable (
+                PrimaryRootPorts,
+                NumberOfRootPorts
+              );
+
+  } else {
+    DEBUG ((
+        DEBUG_INFO, "No PCI Root port found on this bridge!\n"
+    ));
+  }
+
+  DEBUG ((
+      DEBUG_INFO, "<<********** RecordPciRootPortBridges - end **********>>\n"
+  ));
+  return Status;
+}
+
+/**
+  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
+EnumerateOtherPciFeatures (
+  IN PCI_IO_DEVICE          *RootBridge
+  )
+{
+  EFI_STATUS            Status;
+  CHAR16                *Str;
+  UINTN                 OtherPciFeatureConfigPhase;
+
+  //
+  // check on PCI features configuration is complete and re-enumeration is required
+  //
+  if ( !CheckPciFeaturesConfigurationRequired ( RootBridge)) {
+    return EFI_ALREADY_STARTED;
+  }
+
+  Str = ConvertDevicePathToText (
+          DevicePathFromHandle (RootBridge->Handle),
+          FALSE,
+          FALSE
+        );
+  DEBUG ((DEBUG_INFO, "Enumerating PCI features for Root Bridge %s\n", Str != NULL ? Str : L""));
+
+  for ( OtherPciFeatureConfigPhase = PciFeatureRootBridgeScan
+      ; OtherPciFeatureConfigPhase <= PciFeatureConfigurationComplete
+      ; OtherPciFeatureConfigPhase++
+      ) {
+    switch ( OtherPciFeatureConfigPhase){
+      case  PciFeatureRootBridgeScan:
+        SetupPciFeaturesConfigurationDefaults ();
+        //
+        //first scan the entire root bridge heirarchy for the primary PCI root ports
+        //
+        RecordPciRootPortBridges ( RootBridge);
+        break;
+
+      case  PciFeatureGetDevicePolicy:
+      case  PciFeatureSetupPhase:
+        DEBUG ((
+            DEBUG_INFO, "<<********** SetupPciFeatures - start **********>>\n"
+        ));
+        //
+        // enumerate the other PCI features
+        //
+        Status = SetupPciFeatures ( RootBridge, OtherPciFeatureConfigPhase);
+
+        DEBUG ((
+            DEBUG_INFO, "<<********** SetupPciFeatures - end **********>>\n"
+        ));
+        break;
+
+      case  PciFeatureConfigurationPhase:
+        //
+        // override the PCI features as per enumeration phase
+        //
+        DEBUG ((DEBUG_INFO, "PCI features override for Root Bridge %s\n", Str != NULL ? Str : L""));
+        DEBUG ((
+            DEBUG_INFO, "<<********** ProgramPciFeatures - start **********>>\n"
+        ));
+        Status = ProgramPciFeatures ( RootBridge);
+        DEBUG ((
+            DEBUG_INFO, "<<********** ProgramPciFeatures - end **********>>\n"
+        ));
+        break;
+
+      case  PciFeatureConfigurationComplete:
+        //
+        // clean up the temporary resource nodes created for this root bridge
+        //
+        DestroyPrimaryRootPortNodes ();
+
+        ErasePciFeaturesConfigurationTable ();
+    }
+  }
+
+  if (Str != NULL) {
+    FreePool (Str);
+  }
+  //
+  // mark this root bridge as PCI features configuration complete, and no new
+  // enumeration is required
+  //
+  AddRootBridgeInPciFeaturesConfigCompletionList ( RootBridge, FALSE);
+  return Status;
+}
+
+/**
+  This routine is invoked from the Stop () interface for the EFI handle of the
+  RootBridge. Free up its node of type PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
+
+  @param  RootBridge      A pointer to the PCI_IO_DEVICE
+**/
+VOID
+DestroyRootBridgePciFeaturesConfigCompletionList (
+  IN PCI_IO_DEVICE          *RootBridge
+  )
+{
+  LIST_ENTRY                                  *Link;
+  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST   *Temp;
+
+  if ( mPciFeaturesConfigurationCompletionList) {
+    Link = &mPciFeaturesConfigurationCompletionList->RootBridgeLink;
+
+    do {
+      Temp = PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK (Link);
+      if ( Temp->RootBridgeHandle == RootBridge->Handle) {
+        RemoveEntryList ( Link);
+        FreePool ( Temp);
+        return;
+      }
+      Link = Link->ForwardLink;
+    } while (Link != &mPciFeaturesConfigurationCompletionList->RootBridgeLink);
+  }
+  //
+  // not found on the PCI feature configuration completion list, return
+  //
+  return;
+}
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
new file mode 100644
index 0000000000..9f225fa993
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
@@ -0,0 +1,201 @@
+/** @file
+  PCI standard feature support functions implementation for PCI Bus module..
+
+Copyright (c) 2019, 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_
+
+#include "PciBus.h"
+#include "PciPlatformSupport.h"
+
+//
+// Macro definitions for the PCI Features support PCD
+//
+#define PCI_FEATURE_SUPPORT_FLAG_MPS  BIT0
+#define PCI_FEATURE_SUPPORT_FLAG_MRRS BIT1
+
+//
+// defines the data structure to hold the details of the PCI Root port devices
+//
+typedef struct _PRIMARY_ROOT_PORT_NODE  PRIMARY_ROOT_PORT_NODE;
+
+//
+// defines the data structure to hold the configuration data for the other PCI
+// features
+//
+typedef struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE  OTHER_PCI_FEATURES_CONFIGURATION_TABLE;
+
+//
+// Defines for the PCI features configuration completion and re-enumeration list
+//
+typedef struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST;
+
+//
+// Signature value for the PCI Root Port node
+//
+#define PCI_ROOT_PORT_SIGNATURE               SIGNATURE_32 ('p', 'c', 'i', 'p')
+
+//
+// Definitions of the PCI Root Port data structure members
+//
+struct _PRIMARY_ROOT_PORT_NODE {
+  //
+  // Signature header
+  //
+  UINT32                                    Signature;
+  //
+  // linked list pointers to next node
+  //
+  LIST_ENTRY                                NeighborRootPort;
+  //
+  // EFI handle of the parent Root Bridge instance
+  //
+  EFI_HANDLE                                RootBridgeHandle;
+  //
+  // EFI handle of the PCI controller
+  //
+  EFI_HANDLE                                RootPortHandle;
+  //
+  // PCI Secondary bus value of the PCI controller
+  //
+  UINT8                                     SecondaryBusStart;
+  //
+  // PCI Subordinate bus value of the PCI controller
+  //
+  UINT8                                     SecondaryBusEnd;
+  //
+  // pointer to the corresponding PCI feature configuration Table node
+  //
+  OTHER_PCI_FEATURES_CONFIGURATION_TABLE    *OtherPciFeaturesConfigurationTable;
+};
+
+#define PRIMARY_ROOT_PORT_NODE_FROM_LINK(a) \
+  CR (a, PRIMARY_ROOT_PORT_NODE, NeighborRootPort, PCI_ROOT_PORT_SIGNATURE)
+
+//
+// Definition of the PCI Feature configuration Table members
+//
+struct _OTHER_PCI_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;
+  //
+  // 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;
+};
+
+
+//
+// PCI feature configuration node signature value
+//
+#define PCI_FEATURE_CONFIGURATION_SIGNATURE               SIGNATURE_32 ('p', 'c', 'i', 'f')
+
+struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
+  //
+  // Signature header
+  //
+  UINT32                                    Signature;
+  //
+  // link to next Root Bridge whose PCI Feature configuration is complete
+  //
+  LIST_ENTRY                                RootBridgeLink;
+  //
+  // EFI handle of the Root Bridge whose PCI feature configuration is complete
+  //
+  EFI_HANDLE                                RootBridgeHandle;
+  //
+  // indication for complete re-enumeration of the PCI feature configuration
+  //
+  BOOLEAN                                   ReEnumeratePciFeatureConfiguration;
+};
+
+#define PCI_FEATURE_CONFIGURATION_COMPLETION_LIST_FROM_LINK(a) \
+  CR (a, PCI_FEATURE_CONFIGURATION_COMPLETION_LIST, RootBridgeLink, PCI_FEATURE_CONFIGURATION_SIGNATURE)
+
+//
+// Declaration of the internal sub-phases within the PCI Feature enumeration
+//
+typedef enum {
+  //
+  // initial phase in configuring the other PCI features to record the primary
+  // root ports
+  //
+  PciFeatureRootBridgeScan,
+  //
+  // get the PCI device-specific platform policies and align with device capabilities
+  //
+  PciFeatureGetDevicePolicy,
+  //
+  // align all PCI nodes in the PCI heirarchical tree
+  //
+  PciFeatureSetupPhase,
+  //
+  // finally override to complete configuration of the PCI feature
+  //
+  PciFeatureConfigurationPhase,
+  //
+  // PCI feature configuration complete
+  //
+  PciFeatureConfigurationComplete
+
+}PCI_FEATURE_CONFIGURATION_PHASE;
+
+/**
+  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
+CheckOtherPciFeaturesPcd (
+  );
+
+/**
+  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
+EnumerateOtherPciFeatures (
+  IN PCI_IO_DEVICE           *RootBridge
+  );
+
+/**
+  This routine is invoked from the Stop () interface for the EFI handle of the
+  RootBridge. Free up its node of type PCI_FEATURE_CONFIGURATION_COMPLETION_LIST.
+
+  @param  RootBridge      A pointer to the PCI_IO_DEVICE
+**/
+VOID
+DestroyRootBridgePciFeaturesConfigCompletionList (
+  IN PCI_IO_DEVICE          *RootBridge
+  );
+#endif
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
new file mode 100644
index 0000000000..d94037d69a
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
@@ -0,0 +1,565 @@
+/** @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) 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PciPlatformSupport.h"
+
+EFI_PCI_PLATFORM_PROTOCOL                     *mPciPlatformProtocol;
+EFI_PCI_OVERRIDE_PROTOCOL                     *mPciOverrideProtocol;
+
+EFI_PCI_PLATFORM_PROTOCOL2                    *mPciPlatformProtocol2;
+EFI_PCI_OVERRIDE_PROTOCOL2                    *mPciOverrideProtocol2;
+
+
+/**
+  This function retrieves the PCI Platform Protocol published by platform driver
+
+**/
+VOID
+GetPciPlatformProtocol (
+  )
+{
+  mPciPlatformProtocol2 = NULL;
+  gBS->LocateProtocol (
+      &gEfiPciPlatformProtocol2Guid,
+      NULL,
+      (VOID **) &mPciPlatformProtocol2
+  );
+
+  //
+  // If PCI Platform protocol doesn't exist, try to get Pci Override Protocol.
+  //
+  if (mPciPlatformProtocol2 == NULL) {
+    mPciOverrideProtocol2 = NULL;
+    gBS->LocateProtocol (
+        &gEfiPciOverrideProtocol2Guid,
+        NULL,
+        (VOID **) &mPciOverrideProtocol2
+    );
+  }
+  //
+  // fetch the old PCI Platform Protocols if new are not installed
+  //
+  if (mPciOverrideProtocol2 == NULL) {
+
+    mPciPlatformProtocol = NULL;
+    gBS->LocateProtocol (
+        &gEfiPciPlatformProtocolGuid,
+        NULL,
+        (VOID **) &mPciPlatformProtocol
+    );
+
+    //
+    // If PCI Platform protocol doesn't exist, try to  get Pci Override Protocol.
+    //
+    if (mPciPlatformProtocol == NULL) {
+      mPciOverrideProtocol = NULL;
+      gBS->LocateProtocol (
+          &gEfiPciOverrideProtocolGuid,
+          NULL,
+          (VOID **) &mPciOverrideProtocol
+      );
+    }
+  }
+}
+
+/**
+  This function indicates the presence of PCI Platform driver
+  @retval     TRUE or FALSE
+**/
+BOOLEAN
+CheckPciPlatformProtocolInstall (
+  )
+{
+  if (mPciPlatformProtocol2 != NULL) {
+    return TRUE;
+  } else if (mPciOverrideProtocol2 != NULL) {
+    return TRUE;
+  } else {
+    if (mPciPlatformProtocol != NULL) {
+      return TRUE;
+    } else if (mPciOverrideProtocol != NULL){
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+/**
+  Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
+  stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
+  PCI controllers before enumeration.
+
+  This function is called during the PCI enumeration process. No specific action is expected from this
+  member function. It allows the host bridge driver to preinitialize individual PCI controllers before
+  enumeration.
+
+  @param[in] HostBridgeHandle     The associated PCI host bridge handle.
+  @param[in] RootBridgeHandle     The associated PCI root bridge handle.
+  @param[in] RootBridgePciAddress The address of the PCI device on the PCI bus.
+  @param[in] Phase          The phase of the PCI controller enumeration.
+  @param[in] ExecPhase      Defines the execution phase of the PCI chipset driver.
+
+  @retval    Status         returns the status from the PCI Platform protocol as is
+
+**/
+EFI_STATUS
+PciPlatformPreprocessController (
+  IN EFI_HANDLE                                    HostBridgeHandle,
+  IN EFI_HANDLE                                    RootBridgeHandle,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS   RootBridgePciAddress,
+  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE  Phase,
+  IN EFI_PCI_EXECUTION_PHASE                       ExecPhase
+  )
+{
+  EFI_STATUS  Status;
+
+  if (mPciPlatformProtocol2 != NULL) {
+    //
+    // Call PlatformPci::PrepController() if the protocol is present.
+    //
+    Status = mPciPlatformProtocol2->PlatformPrepController (
+                                      (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
+                                      HostBridgeHandle,
+                                      RootBridgeHandle,
+                                      RootBridgePciAddress,
+                                      Phase,
+                                      ExecPhase
+                                    );
+  } else if (mPciOverrideProtocol2 != NULL) {
+    //
+    // Call PlatformPci::PrepController() if the protocol is present.
+    //
+    Status = mPciOverrideProtocol2->PlatformPrepController (
+                                      (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
+                                      HostBridgeHandle,
+                                      RootBridgeHandle,
+                                      RootBridgePciAddress,
+                                      Phase,
+                                      ExecPhase
+                                    );
+  } else {
+    if (mPciPlatformProtocol != NULL) {
+      //
+      // Call PlatformPci::PrepController() if the protocol is present.
+      //
+      Status = mPciPlatformProtocol->PlatformPrepController (
+                                      mPciPlatformProtocol,
+                                      HostBridgeHandle,
+                                      RootBridgeHandle,
+                                      RootBridgePciAddress,
+                                      Phase,
+                                      ExecPhase
+                                    );
+    } else if (mPciOverrideProtocol != NULL) {
+      //
+      // Call PlatformPci::PrepController() if the protocol is present.
+      //
+      Status = mPciOverrideProtocol->PlatformPrepController (
+                                      mPciOverrideProtocol,
+                                      HostBridgeHandle,
+                                      RootBridgeHandle,
+                                      RootBridgePciAddress,
+                                      Phase,
+                                      ExecPhase
+                                    );
+    } else {
+      //
+      // return PCI Platform Protocol not found
+      //
+      return EFI_NOT_FOUND;
+    }
+  }
+  return Status;
+}
+
+/**
+  This function notifies the PCI Platform driver about the PCI host bridge resource
+  allocation phase and PCI execution phase.
+
+  @param[in]  HostBridge     The handle of the host bridge controller.
+  @param[in]  Phase          The phase of the PCI bus enumeration.
+  @param[in]  ExecPhase      Defines the execution phase of the PCI chipset driver.
+  @retval     Status          returns the status from the PCI Platform protocol as is
+
+**/
+EFI_STATUS
+PciPlatformNotifyPhase (
+  IN  EFI_HANDLE                                      HostBridgeHandle,
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE   Phase,
+  IN  EFI_PCI_EXECUTION_PHASE                         ExecPhase
+  )
+{
+  EFI_STATUS  Status;
+
+  if ( mPciPlatformProtocol2 != NULL) {
+    Status = mPciPlatformProtocol2->PlatformNotify (
+                                      (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
+                                      HostBridgeHandle,
+                                      Phase,
+                                      ExecPhase
+                                    );
+  } else if ( mPciOverrideProtocol2 != NULL) {
+    Status = mPciOverrideProtocol2->PlatformNotify (
+                                      (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
+                                      HostBridgeHandle,
+                                      Phase,
+                                      ExecPhase
+                                    );
+  } else {
+
+    if ( mPciPlatformProtocol != NULL) {
+      Status = mPciPlatformProtocol->PlatformNotify (
+                                      mPciPlatformProtocol,
+                                      HostBridgeHandle,
+                                      Phase,
+                                      ExecPhase
+                                    );
+    } else if ( mPciOverrideProtocol != NULL){
+      Status = mPciOverrideProtocol->PlatformNotify (
+                                      mPciOverrideProtocol,
+                                      HostBridgeHandle,
+                                      Phase,
+                                      ExecPhase
+                                    );
+    } else {
+      //
+      // return PCI Platform Protocol not found
+      //
+      return EFI_NOT_FOUND;
+    }
+  }
+  return Status;
+}
+
+/**
+  This function retrieves the PCI platform policy.
+
+  @param  PciPolicy     pointer to the legacy EFI_PCI_PLATFORM_POLICY
+  @retval Status        returns the status from the PCI Platform protocol as is
+
+**/
+EFI_STATUS
+PciGetPlatformPolicy (
+  OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
+  )
+{
+  EFI_STATUS  Status;
+
+  if ( mPciPlatformProtocol2 != NULL) {
+      Status = mPciPlatformProtocol2->GetPlatformPolicy (
+                                        (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
+                                        PciPolicy
+                                      );
+  } else if ( mPciOverrideProtocol2 != NULL) {
+      Status = mPciOverrideProtocol2->GetPlatformPolicy (
+                                        (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
+                                        PciPolicy
+                                      );
+  } else {
+    if ( mPciPlatformProtocol != NULL) {
+      Status = mPciPlatformProtocol->GetPlatformPolicy (
+                                      mPciPlatformProtocol,
+                                      PciPolicy
+                                    );
+    }
+
+    if ( mPciOverrideProtocol != NULL) {
+      Status = mPciOverrideProtocol->GetPlatformPolicy (
+                                      mPciOverrideProtocol,
+                                      PciPolicy
+                                    );
+    } else {
+      //
+      // return PCI Platform Protocol not found
+      //
+      return EFI_NOT_FOUND;
+    }
+  }
+  return Status;
+}
+
+/**
+  This function retrieves the Option ROM image and size from the Platform.
+
+  It uses the PCI_IO_DEVICE internal fields are used to store OpROM image/size
+
+  @param Controller     An EFI handle for the PCI bus controller.
+  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO device to be registered.
+
+  @retval EFI_SUCCESS            The option ROM was available for this device and loaded into memory.
+  @retval EFI_NOT_FOUND          No option ROM was available for this device.
+  @retval EFI_OUT_OF_RESOURCES   No memory was available to load the option ROM.
+  @retval EFI_DEVICE_ERROR       An error occurred in obtaining the option ROM.
+
+**/
+EFI_STATUS
+GetPlatformPciOptionRom (
+  IN  EFI_HANDLE                    Controller,
+  IN  PCI_IO_DEVICE                 *PciIoDevice
+  )
+{
+  EFI_STATUS  Status;
+  VOID        *PlatformOpRomBuffer;
+  UINTN       PlatformOpRomSize;
+
+  if (mPciPlatformProtocol2 != NULL) {
+    Status = mPciPlatformProtocol2->GetPciRom (
+                                      (EFI_PCI_PLATFORM_PROTOCOL*)mPciPlatformProtocol2,
+                                      PciIoDevice->Handle,
+                                      &PlatformOpRomBuffer,
+                                      &PlatformOpRomSize
+                                      );
+  } else if (mPciOverrideProtocol2 != NULL) {
+    Status = mPciOverrideProtocol2->GetPciRom (
+                                      (EFI_PCI_PLATFORM_PROTOCOL*)mPciOverrideProtocol2,
+                                      PciIoDevice->Handle,
+                                      &PlatformOpRomBuffer,
+                                      &PlatformOpRomSize
+                                      );
+  } else {
+    if (mPciPlatformProtocol != NULL) {
+      Status = mPciPlatformProtocol->GetPciRom (
+                                      mPciPlatformProtocol,
+                                      PciIoDevice->Handle,
+                                      &PlatformOpRomBuffer,
+                                      &PlatformOpRomSize
+                                      );
+    } else if (mPciOverrideProtocol != NULL) {
+      Status = mPciOverrideProtocol->GetPciRom (
+                                        mPciOverrideProtocol,
+                                        PciIoDevice->Handle,
+                                        &PlatformOpRomBuffer,
+                                        &PlatformOpRomSize
+                                        );
+    } else {
+      //
+      // return PCI Platform Protocol not found
+      //
+      return EFI_NOT_FOUND;
+    }
+  }
+
+  if (!EFI_ERROR (Status)) {
+    PciIoDevice->EmbeddedRom    = FALSE;
+    PciIoDevice->RomSize        = (UINT32)PlatformOpRomSize;
+    PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;
+    PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;
+  }
+  return Status;
+}
+
+/**
+  Helper routine to indicate whether the given PCI device specific policy value
+  dictates to override the Max_Payload_Size to a particular value, or set as per
+  device capability.
+
+  @param  MPS     Input device-specific policy should be in terms of type
+                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
+
+  @retval TRUE    Setup Max_Payload_Size as per device capability
+          FALSE   override as per device-specific platform policy
+**/
+BOOLEAN
+SetupMpsAsPerDeviceCapability (
+  IN  UINT8                   MPS
+)
+{
+  if ( MPS == EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+/**
+  Helper routine to indicate whether the given PCI device specific policy value
+  dictates to override the Max_Read_Req_Size to a particular value, or set as per
+  device capability.
+
+  @param  MRRS    Input device-specific policy should be in terms of type
+                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
+
+  @retval TRUE    Setup Max_Read_Req_Size as per device capability
+          FALSE   override as per device-specific platform policy
+**/
+BOOLEAN
+SetupMrrsAsPerDeviceCapability (
+  IN  UINT8                   MRRS
+)
+{
+  if ( MRRS == EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+/**
+  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
+TranslateMpsSetupValueToPci (
+  IN  UINT8                   MPS
+)
+{
+  switch (MPS) {
+    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_128B:
+      return PCIE_MAX_PAYLOAD_SIZE_128B;
+    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_256B:
+      return PCIE_MAX_PAYLOAD_SIZE_256B;
+    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_512B:
+      return PCIE_MAX_PAYLOAD_SIZE_512B;
+    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_1024B:
+      return PCIE_MAX_PAYLOAD_SIZE_1024B;
+    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_2048B:
+      return PCIE_MAX_PAYLOAD_SIZE_2048B;
+    case EFI_PCI_CONF_MAX_PAYLOAD_SIZE_4096B:
+      return PCIE_MAX_PAYLOAD_SIZE_4096B;
+    default:
+      return PCIE_MAX_PAYLOAD_SIZE_128B;
+  }
+}
+
+/**
+  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
+TranslateMrrsSetupValueToPci (
+  IN  UINT8                   MRRS
+)
+{
+  switch (MRRS) {
+    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_128B:
+      return PCIE_MAX_READ_REQ_SIZE_128B;
+    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_256B:
+      return PCIE_MAX_READ_REQ_SIZE_256B;
+    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_512B:
+      return PCIE_MAX_READ_REQ_SIZE_512B;
+    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_1024B:
+      return PCIE_MAX_READ_REQ_SIZE_1024B;
+    case EFI_PCI_CONF_MAX_READ_REQ_SIZE_2048B:
+      return PCIE_MAX_READ_REQ_SIZE_2048B;
+    case EFI_PCI_CONF_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.
+**/
+VOID
+SetupDefaultsDevicePlatformPolicy (
+  IN  PCI_IO_DEVICE               *PciDevice
+  )
+{
+  PciDevice->SetupMPS = EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO;
+  PciDevice->SetupMRRS = EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO;
+}
+
+/**
+  Intermediate routine to either get the PCI device specific platform policies
+  through the PCI Platform Protocol, or its alias the PCI Override Protocol.
+
+  @param  PciIoDevice         A pointer to PCI_IO_DEVICE
+  @param  PciPlatformProtocol A pointer to EFI_PCI_PLATFORM_PROTOCOL2
+
+  @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
+GetPciDevicePlatformPolicyEx (
+  IN  PCI_IO_DEVICE               *PciIoDevice,
+  IN  EFI_PCI_PLATFORM_PROTOCOL2  *PciPlatformProtocol
+  )
+{
+  EFI_PCI_PLATFORM_EXTENDED_POLICY  PciPlatformExtendedPolicy;
+  EFI_STATUS                        Status;
+
+  ZeroMem ( &PciPlatformExtendedPolicy, sizeof (EFI_PCI_PLATFORM_EXTENDED_POLICY));
+  Status = PciPlatformProtocol->GetDevicePolicy (
+                                  PciPlatformProtocol,
+                                  PciIoDevice->Handle,
+                                  &PciPlatformExtendedPolicy
+                                  );
+  //
+  // platform chipset policies are returned for this PCI device
+  //
+  if (!EFI_ERROR(Status)) {
+    PciIoDevice->SetupMPS = PciPlatformExtendedPolicy.DeviceCtlMPS;
+    PciIoDevice->SetupMRRS = PciPlatformExtendedPolicy.DeviceCtlMRRS;
+  }
+  //
+  // platform chipset policies are not provided for this PCI device
+  //
+  if (EFI_ERROR(Status) == EFI_UNSUPPORTED) {
+    //
+    // let the enumeration happen as per the PCI standard way
+    //
+    SetupDefaultsDevicePlatformPolicy ( PciIoDevice);
+    return EFI_SUCCESS;
+  }
+
+  return Status;
+}
+
+/**
+  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
+GetPciDevicePlatformPolicy (
+  IN PCI_IO_DEVICE          *PciDevice
+  )
+{
+  if ( mPciPlatformProtocol2 != NULL) {
+    return GetPciDevicePlatformPolicyEx ( PciDevice, mPciPlatformProtocol2);
+  } else if (mPciOverrideProtocol2 != NULL) {
+    return GetPciDevicePlatformPolicyEx ( PciDevice, mPciOverrideProtocol2);
+  } else {
+    //
+    // new PCI Platform Protocol 2 is not installed; let the enumeration happen
+    // as per PCI standard way
+    //
+    SetupDefaultsDevicePlatformPolicy ( PciDevice);
+    return EFI_SUCCESS;
+  }
+}
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
new file mode 100644
index 0000000000..d54e46b950
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
@@ -0,0 +1,193 @@
+/** @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) 2019, 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_
+
+#include "PciBus.h"
+
+/**
+  This function retrieves the PCI Platform Protocol published by platform driver
+
+**/
+VOID
+GetPciPlatformProtocol (
+  );
+
+/**
+  This function indicates the presence of PCI Platform driver
+  @retval     TRUE or FALSE
+**/
+BOOLEAN
+CheckPciPlatformProtocolInstall (
+  );
+
+
+/**
+  Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
+  stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
+  PCI controllers before enumeration.
+
+  This function is called during the PCI enumeration process. No specific action is expected from this
+  member function. It allows the host bridge driver to preinitialize individual PCI controllers before
+  enumeration.
+
+  @param[in] HostBridgeHandle     The associated PCI host bridge handle.
+  @param[in] RootBridgeHandle     The associated PCI root bridge handle.
+  @param[in] RootBridgePciAddress The address of the PCI device on the PCI bus.
+  @param[in] Phase          The phase of the PCI controller enumeration.
+  @param[in] ExecPhase      Defines the execution phase of the PCI chipset driver.
+
+  @retval    Status         returns the status from the PCI Platform protocol as is
+
+**/
+EFI_STATUS
+PciPlatformPreprocessController (
+  IN EFI_HANDLE                                    HostBridgeHandle,
+  IN EFI_HANDLE                                    RootBridgeHandle,
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS   RootBridgePciAddress,
+  IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE  Phase,
+  IN EFI_PCI_EXECUTION_PHASE                       ExecPhase
+  );
+
+/**
+  This function notifies the PCI Platform driver about the PCI host bridge resource
+  allocation phase and PCI execution phase.
+
+  @param[in]  HostBridge     The handle of the host bridge controller.
+  @param[in]  Phase          The phase of the PCI bus enumeration.
+  @param[in]  ExecPhase      Defines the execution phase of the PCI chipset driver.
+  @retval     Status          returns the status from the PCI Platform protocol as is
+
+**/
+EFI_STATUS
+PciPlatformNotifyPhase (
+  IN  EFI_HANDLE                                      HostBridgeHandle,
+  IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE   Phase,
+  IN  EFI_PCI_EXECUTION_PHASE                         ExecPhase
+  );
+
+/**
+  This function retrieves the PCI platform policy.
+
+  @param  PciPolicy     pointer to the legacy EFI_PCI_PLATFORM_POLICY
+  @retval Status        returns the status from the PCI Platform protocol as is
+
+**/
+EFI_STATUS
+PciGetPlatformPolicy (
+  OUT EFI_PCI_PLATFORM_POLICY *PciPolicy
+  );
+
+/**
+  This function retrieves the Option ROM image and size from the Platform.
+
+  It uses the PCI_IO_DEVICE internal fields are used to store OpROM image/size
+
+  @param Controller     An EFI handle for the PCI bus controller.
+  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO device to be registered.
+
+  @retval EFI_SUCCESS            The option ROM was available for this device and loaded into memory.
+  @retval EFI_NOT_FOUND          No option ROM was available for this device.
+  @retval EFI_OUT_OF_RESOURCES   No memory was available to load the option ROM.
+  @retval EFI_DEVICE_ERROR       An error occurred in obtaining the option ROM.
+
+**/
+EFI_STATUS
+GetPlatformPciOptionRom (
+  IN  EFI_HANDLE                    Controller,
+  IN  PCI_IO_DEVICE                 *PciIoDevice
+  );
+
+/**
+  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
+GetPciDevicePlatformPolicy (
+  IN PCI_IO_DEVICE          *PciDevice
+  );
+
+/**
+  Helper routine to indicate whether the given PCI device specific policy value
+  dictates to override the Max_Payload_Size to a particular value, or set as per
+  device capability.
+
+  @param  MPS     Input device-specific policy should be in terms of type
+                  EFI_PCI_CONF_MAX_PAYLOAD_SIZE
+
+  @retval TRUE    Setup Max_Payload_Size as per device capability
+          FALSE   override as per device-specific platform policy
+**/
+BOOLEAN
+SetupMpsAsPerDeviceCapability (
+  IN  UINT8                   MPS
+);
+
+/**
+  Helper routine to indicate whether the given PCI device specific policy value
+  dictates to override the Max_Read_Req_Size to a particular value, or set as per
+  device capability.
+
+  @param  MRRS    Input device-specific policy should be in terms of type
+                  EFI_PCI_CONF_MAX_READ_REQ_SIZE
+
+  @retval TRUE    Setup Max_Read_Req_Size as per device capability
+          FALSE   override as per device-specific platform policy
+**/
+BOOLEAN
+SetupMrrsAsPerDeviceCapability (
+  IN  UINT8                   MRRS
+);
+
+/**
+  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
+TranslateMpsSetupValueToPci (
+  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
+TranslateMrrsSetupValueToPci (
+  IN  UINT8                   MRRS
+);
+#endif
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
index 4969ee0f64..755423f77b 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
@@ -198,20 +198,7 @@ CalculateApertureIo16 (
     //
     Status = EFI_NOT_FOUND;
     PciPolicy = 0;
-    if (gPciPlatformProtocol != NULL) {
-      Status = gPciPlatformProtocol->GetPlatformPolicy (
-                                       gPciPlatformProtocol,
-                                       &PciPolicy
-                                       );
-    }
-
-    if (EFI_ERROR (Status) && gPciOverrideProtocol != NULL) {
-      Status = gPciOverrideProtocol->GetPlatformPolicy (
-                                       gPciOverrideProtocol,
-                                       &PciPolicy
-                                       );
-    }
-
+    Status = PciGetPlatformPolicy ( &PciPolicy);
     if (!EFI_ERROR (Status)) {
       if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) != 0) {
         mReserveIsaAliases = TRUE;
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 17beb45235..7bcbe5a3ea 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -1026,6 +1026,16 @@
   # @Prompt Enable UEFI Stack Guard.
   gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard|FALSE|BOOLEAN|0x30001055
 
+  ## This PCD is to indicate the PCI Bus driver to setup other new PCI features.
+  #  Each PCI feature is represented by its mask bit position and it configures
+  #  if that bit is set.
+  #
+  #   Bit 0 - if set, the PCI Bus driver programs the device's Max_Payload_Size.<BR>
+  #   Bit 1 - if set, the PCI Bus driver programs the device's Max_Read_Req_Size.<BR>
+  #   Bit 2 to 31 - Reserved for future use by the PCI Bus driver.<BR>
+  # @Prompt The UEFI PCU Bus driver enables the new set of other PCI Features.
+  gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures|0x00000003|UINT32|0x30001056
+
 [PcdsFixedAtBuild, PcdsPatchableInModule]
   ## Dynamic type PCD can be registered callback function for Pcd setting action.
   #  PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the maximum number of callback function
-- 
2.21.0.windows.1


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

end of thread, other threads:[~2019-10-21 10:26 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-09-23 14:20 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH] PciBusDxe: New PCI features Max_Payload_Size, Max_Read_Req_Size Javeed, Ashraf
2019-10-14  6:57 ` Ni, Ray
2019-10-14  9:52   ` Ni, Ray
2019-10-15  5:28     ` Javeed, Ashraf
2019-10-15  7:48       ` Ni, Ray
2019-10-15  8:49         ` Javeed, Ashraf
2019-10-15  9:49           ` Ni, Ray
2019-10-15 10:16             ` Javeed, Ashraf
     [not found]             ` <15CDCA9B4F890B1A.1108@groups.io>
2019-10-17 14:45               ` [edk2-devel] " Javeed, Ashraf
2019-10-21  5:35                 ` Ni, Ray
2019-10-21  5:39                   ` Liming Gao
2019-10-21 10:26                     ` Javeed, Ashraf

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