From d40483911c83dbcff1cb25ae4c9b9c26cf213973 Mon Sep 17 00:00:00 2001
From: rsun3 <rsun3@6f19259b-4bc3-4df7-8a09-765794883524>
Date: Tue, 13 Jul 2010 01:58:47 +0000
Subject: [PATCH] =?UTF-8?q?Fix=20bugs=20in=20the=20PCI=20bus=20driver=20to?=
 =?UTF-8?q?=20support=20SR-IOV.=201.=20Expand=20the=20type=20of=20Offset?=
 =?UTF-8?q?=20in=20the=20=5FPCI=5FBAR=20structure=20from=20UINT8=20to=20UI?=
 =?UTF-8?q?NT16,=20because=20a=20VF=20BAR=E2=80=99s=20offset=20may=20be=20?=
 =?UTF-8?q?>=3D=200x100;=202.=20Enable=20ARI=20Capable=20Hierarchy=20for?=
 =?UTF-8?q?=20SR-IOV=20devices=20at=20earlier=20time=20because=20FirstVFOf?=
 =?UTF-8?q?fset=20and=20VFStride=20of=20a=20SR-IOV=20device=20may=20change?=
 =?UTF-8?q?=20after=20its=20ARI=20Capable=20Hierarchy=20is=20set;=203.=20C?=
 =?UTF-8?q?hange=20type=20of=20PcdSrIovSupport,=20PcdAriSupport,=20PcdMrIo?=
 =?UTF-8?q?vSupport=20from=20FeatureFlag=20to=20[FixAtBuild,=20PcdDynamics?=
 =?UTF-8?q?],=20which=20allows=20SR-IOV/MR-IOV/ARI=20feature=20can=20be=20?=
 =?UTF-8?q?turn=20on/off=20dynamically,=20typically=20via=20a=20setup=20op?=
 =?UTF-8?q?tion.=204.=20Change=20PCI=20bus=20scan=20algorithm=20in=20PciSc?=
 =?UTF-8?q?anBus()=20to=20prevent=20the=20case=20where=20some=20ARI=20exte?=
 =?UTF-8?q?nded=20functions=20may=20be=20skipped=20in=20the=20scan=20loop.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10644 6f19259b-4bc3-4df7-8a09-765794883524
---
 MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h       |   4 +-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf  |   6 +-
 .../Bus/Pci/PciBusDxe/PciDeviceSupport.c      |  36 +-
 .../Bus/Pci/PciBusDxe/PciEnumeratorSupport.c  | 395 +++++++++++-------
 .../Bus/Pci/PciBusDxe/PciEnumeratorSupport.h  |   6 +-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c       |  82 ++--
 6 files changed, 295 insertions(+), 234 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index 6c17767623..8517c60f72 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -1,7 +1,7 @@
 /** @file
   Header files and data structures needed by PCI Bus module.
 
-Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials
 are licensed and made available under the terms and conditions of the BSD License
 which accompanies this distribution.  The full text of the license may be found at
@@ -104,7 +104,7 @@ struct _PCI_BAR {
   PCI_BAR_TYPE  BarType;
   BOOLEAN       Prefetchable;
   UINT8         MemType;
-  UINT8         Offset;
+  UINT16        Offset;
 };
 
 //
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
index 214611181d..7096b11618 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
@@ -100,13 +100,13 @@
 
 [FeaturePcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport
-  gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSupport
-  gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport
-  gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport
   gEfiMdeModulePkgTokenSpaceGuid.PcdPciBridgeIoAlignmentProbe
 
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSystemPageSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSrIovSupport
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport
 
 # [Event]
 #   ##
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
index 0d1518a43d..1ad863c966 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
@@ -1,7 +1,7 @@
 /** @file
   Supporting functions implementaion for PCI devices management.
 
-Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials
 are licensed and made available under the terms and conditions of the BSD License
 which accompanies this distribution.  The full text of the license may be found at
@@ -215,10 +215,6 @@ RegisterPciDevice (
   EFI_PCI_IO_PROTOCOL *PciIo;
   UINT8               Data8;
   BOOLEAN             HasEfiImage;
-  PCI_IO_DEVICE       *ParrentPciIoDevice;
-  EFI_PCI_IO_PROTOCOL *ParrentPciIo;
-  UINT16              Data16;
-  UINT32              Data32;
 
   //
   // Install the pciio protocol, device path protocol
@@ -255,35 +251,7 @@ RegisterPciDevice (
   PciIo = &(PciIoDevice->PciIo);
   Data8 = PCI_INT_LINE_UNKNOWN;
   PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &Data8);
-  
-  //
-  // PCI-IOV programming
-  //
-  if (((FeaturePcdGet(PcdAriSupport) & EFI_PCI_IOV_POLICY_ARI) != 0) && (PciIoDevice->AriCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport) & EFI_PCI_IOV_POLICY_SRIOV) != 0) &&
-      (PciIoDevice->SrIovCapabilityOffset != 0)) {
-    //
-    // Check its parrent ARI forwarding capability
-    //
-    ParrentPciIoDevice = PciIoDevice->Parent;
-    ParrentPciIo = &(ParrentPciIoDevice->PciIo);
-    ParrentPciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ParrentPciIoDevice->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET, 1, &Data32);
-    if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING) != 0) {
-      //
-      // ARI forward support in bridge, so enable it.
-      //
-      ParrentPciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ParrentPciIoDevice->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET, 1, &Data32);
-      Data32 |= EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING;
-      ParrentPciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ParrentPciIoDevice->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET, 1, &Data32);
-
-      //
-      // Set ARI Capable Hierarchy for device
-      //
-      PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL, 1, &Data16);
-      Data16 |= EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY;
-      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL, 1, &Data16);
-    }
-  }
-  
+ 
   //
   // Process OpRom
   //
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
index e67777fab1..f2108284d3 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
@@ -328,11 +328,9 @@ GatherDeviceInfo (
   UINTN                           Offset;
   UINTN                           BarIndex;
   PCI_IO_DEVICE                   *PciIoDevice;
-  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
 
-  PciRootBridgeIo = Bridge->PciRootBridgeIo;
   PciIoDevice = CreatePciIoDevice (
-                  PciRootBridgeIo,
+                  Bridge,
                   Pci,
                   Bus,
                   Device,
@@ -370,7 +368,7 @@ GatherDeviceInfo (
   //
   // Parse the SR-IOV VF bars
   //
-  if ((PciIoDevice->SrIovCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {
+  if (PcdGetBool (PcdSrIovSupport) && PciIoDevice->SrIovCapabilityOffset != 0) {
     for (Offset = PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR0, BarIndex = 0;
          Offset <= PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_BAR5;
          BarIndex++) {
@@ -403,16 +401,14 @@ GatherPpbInfo (
   IN UINT8                            Func
   )
 {
-  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
   PCI_IO_DEVICE                   *PciIoDevice;
   EFI_STATUS                      Status;
   UINT8                           Value;
   EFI_PCI_IO_PROTOCOL             *PciIo;
   UINT8                           Temp;
 
-  PciRootBridgeIo = Bridge->PciRootBridgeIo;
   PciIoDevice = CreatePciIoDevice (
-                  PciRootBridgeIo,
+                  Bridge,
                   Pci,
                   Bus,
                   Device,
@@ -558,12 +554,10 @@ GatherP2CInfo (
   IN UINT8                            Func
   )
 {
-  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
   PCI_IO_DEVICE                   *PciIoDevice;
 
-  PciRootBridgeIo = Bridge->PciRootBridgeIo;
   PciIoDevice = CreatePciIoDevice (
-                  PciRootBridgeIo,
+                  Bridge,
                   Pci,
                   Bus,
                   Device,
@@ -1415,11 +1409,11 @@ PciIovParseVfBar (
     //
     // Scan all the BARs anyway
     //
-    PciIoDevice->VfPciBar[BarIndex].Offset = (UINT8) Offset;
+    PciIoDevice->VfPciBar[BarIndex].Offset = (UINT16) Offset;
     return Offset + 4;
   }
 
-  PciIoDevice->VfPciBar[BarIndex].Offset = (UINT8) Offset;
+  PciIoDevice->VfPciBar[BarIndex].Offset = (UINT16) Offset;
   if ((Value & 0x01) != 0) {
     //
     // Device I/Os. Impossible
@@ -1905,14 +1899,14 @@ InitializeP2C (
 **/
 PCI_IO_DEVICE *
 CreatePciIoDevice (
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
+  IN PCI_IO_DEVICE                    *Bridge,
   IN PCI_TYPE00                       *Pci,
   IN UINT8                            Bus,
   IN UINT8                            Device,
   IN UINT8                            Func
   )
 {
-  PCI_IO_DEVICE *PciIoDevice;
+  PCI_IO_DEVICE        *PciIoDevice;
   EFI_PCI_IO_PROTOCOL  *PciIo;
   EFI_STATUS           Status;
 
@@ -1923,7 +1917,7 @@ CreatePciIoDevice (
 
   PciIoDevice->Signature        = PCI_IO_DEVICE_SIGNATURE;
   PciIoDevice->Handle           = NULL;
-  PciIoDevice->PciRootBridgeIo  = PciRootBridgeIo;
+  PciIoDevice->PciRootBridgeIo  = Bridge->PciRootBridgeIo;
   PciIoDevice->DevicePath       = NULL;
   PciIoDevice->BusNumber        = Bus;
   PciIoDevice->DeviceNumber     = Device;
@@ -1968,147 +1962,262 @@ CreatePciIoDevice (
     PciIoDevice->IsPciExp = TRUE;
   }
 
-  //
-  // Initialize for PCI IOV
-  //
+  if (PcdGetBool (PcdAriSupport)) {
+    //
+    // Check if the device is an ARI device.
+    //
+    Status = LocatePciExpressCapabilityRegBlock (
+               PciIoDevice,
+               EFI_PCIE_CAPABILITY_ID_ARI,
+               &PciIoDevice->AriCapabilityOffset,
+               NULL
+               );
+    if (!EFI_ERROR (Status)) {
+      //
+      // We need to enable ARI feature before calculate BusReservation,
+      // because FirstVFOffset and VFStride may change after that.
+      //
+      EFI_PCI_IO_PROTOCOL  *ParentPciIo;
+      UINT32               Data32;
 
-  //
-  // Check ARI for function 0 only
-  //
-  Status = LocatePciExpressCapabilityRegBlock (
-             PciIoDevice,
-             EFI_PCIE_CAPABILITY_ID_ARI,
-             &PciIoDevice->AriCapabilityOffset,
-             NULL
-             );
-  if (!EFI_ERROR (Status)) {
-    DEBUG ((
-      EFI_D_INFO,
-      "PCI-IOV B%x.D%x.F%x - ARI Cap offset - 0x%x\n",
-      (UINTN)Bus,
-      (UINTN)Device,
-      (UINTN)Func,
-      (UINTN)PciIoDevice->AriCapabilityOffset
-      ));
-  }
+      //
+      // Check if its parent supports ARI forwarding.
+      //
+      ParentPciIo = &Bridge->PciIo;
+      ParentPciIo->Pci.Read (
+                          ParentPciIo, 
+                          EfiPciIoWidthUint32,
+                          Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET,
+                          1,
+                          &Data32
+                          );
+      if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING) != 0) {
+        //
+        // ARI forward support in bridge, so enable it.
+        //
+        ParentPciIo->Pci.Read (
+                            ParentPciIo,
+                            EfiPciIoWidthUint32,
+                            Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET,
+                            1,
+                            &Data32
+                            );
+        if ((Data32 & EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING) == 0) {
+          Data32 |= EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING;
+          ParentPciIo->Pci.Write (
+                              ParentPciIo,
+                              EfiPciIoWidthUint32,
+                              Bridge->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET,
+                              1,
+                              &Data32
+                              );
+          DEBUG ((
+            EFI_D_INFO,
+            "PCI B%x.D%x.F%x - ARI forwarding enabled\n",
+            (UINTN)Bridge->BusNumber,
+            (UINTN)Bridge->DeviceNumber,
+            (UINTN)Bridge->FunctionNumber
+            ));
+        }
+      }
 
-  Status = LocatePciExpressCapabilityRegBlock (
-             PciIoDevice,
-             EFI_PCIE_CAPABILITY_ID_SRIOV,
-             &PciIoDevice->SrIovCapabilityOffset,
-             NULL
-             );
-  if (!EFI_ERROR (Status)) {
-    DEBUG ((
-      EFI_D_INFO,
-      "PCI-IOV B%x.D%x.F%x - SRIOV Cap offset - 0x%x\n",
-      (UINTN)Bus,
-      (UINTN)Device,
-      (UINTN)Func,
-      (UINTN)PciIoDevice->SrIovCapabilityOffset
-      ));
-  }
-
-  Status = LocatePciExpressCapabilityRegBlock (
-             PciIoDevice,
-             EFI_PCIE_CAPABILITY_ID_MRIOV,
-             &PciIoDevice->MrIovCapabilityOffset,
-             NULL
-             );
-  if (!EFI_ERROR (Status)) {
-    DEBUG ((
-      EFI_D_INFO,
-      "PCI-IOV B%x.D%x.F%x - MRIOV Cap offset - 0x%x\n",
-      (UINTN)Bus,
-      (UINTN)Device,
-      (UINTN)Func,
-      (UINTN)PciIoDevice->MrIovCapabilityOffset
-      ));
+      DEBUG ((
+        EFI_D_INFO,
+        "PCI ARI B%x.D%x.F%x - ARI Cap offset - 0x%x\n",
+        (UINTN)Bus,
+        (UINTN)Device,
+        (UINTN)Func,
+        (UINTN)PciIoDevice->AriCapabilityOffset
+        ));
+    }
   }
 
   //
-  // Calculate SystemPageSize
+  // Initialization for SR-IOV
   //
-  if ((PciIoDevice->SrIovCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {
 
-    PciIo->Pci.Read (
-                 PciIo,
-                 EfiPciIoWidthUint32,
-                 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE,
-                 1,
-                 &PciIoDevice->SystemPageSize
-                 );
-    DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - SupportedPageSize - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, PciIoDevice->SystemPageSize));
+  if (PcdGetBool (PcdSrIovSupport)) {
+    Status = LocatePciExpressCapabilityRegBlock (
+               PciIoDevice,
+               EFI_PCIE_CAPABILITY_ID_SRIOV,
+               &PciIoDevice->SrIovCapabilityOffset,
+               NULL
+               );
+    if (!EFI_ERROR (Status)) {
+      UINT16    VFStride;
+      UINT16    FirstVFOffset;
+      UINT16    Data16;
+      UINT32    PFRid;
+      UINT32    LastVF;
 
-    PciIoDevice->SystemPageSize = (PcdGet32 (PcdSrIovSystemPageSize) & PciIoDevice->SystemPageSize);
-    ASSERT (PciIoDevice->SystemPageSize != 0);
+      //
+      // If the SR-IOV device is an ARI device, then Set ARI Capable Hierarchy for the device.
+      //
+      if (PcdGetBool (PcdAriSupport) && PciIoDevice->AriCapabilityOffset != 0) {
+        PciIo->Pci.Read (
+                     PciIo,
+                     EfiPciIoWidthUint16,
+                     PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL,
+                     1,
+                     &Data16
+                     );
+        Data16 |= EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY;
+        PciIo->Pci.Write (
+                     PciIo,
+                     EfiPciIoWidthUint16,
+                     PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL,
+                     1,
+                     &Data16
+                     );
+      }
 
-    PciIo->Pci.Write (
-                 PciIo,
-                 EfiPciIoWidthUint32,
-                 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE,
-                 1,
-                 &PciIoDevice->SystemPageSize
-                 );
-    DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - SystemPageSize - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, PciIoDevice->SystemPageSize));
-    //
-    // Adjust SystemPageSize for Alignment usage later
-    //
-    PciIoDevice->SystemPageSize <<= 12;
+      //
+      // Calculate SystemPageSize
+      //
+
+      PciIo->Pci.Read (
+                   PciIo,
+                   EfiPciIoWidthUint32,
+                   PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE,
+                   1,
+                   &PciIoDevice->SystemPageSize
+                   );
+      DEBUG ((
+        EFI_D_INFO,
+        "PCI SR-IOV B%x.D%x.F%x - SupportedPageSize - 0x%x\n",
+        (UINTN)Bus,
+        (UINTN)Device,
+        (UINTN)Func,
+        PciIoDevice->SystemPageSize
+        ));
+
+      PciIoDevice->SystemPageSize = (PcdGet32 (PcdSrIovSystemPageSize) & PciIoDevice->SystemPageSize);
+      ASSERT (PciIoDevice->SystemPageSize != 0);
+
+      PciIo->Pci.Write (
+                   PciIo,
+                   EfiPciIoWidthUint32,
+                   PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE,
+                   1,
+                   &PciIoDevice->SystemPageSize
+                   );
+      DEBUG ((
+        EFI_D_INFO,
+        "PCI SR-IOV B%x.D%x.F%x - SystemPageSize - 0x%x\n",
+        (UINTN)Bus,
+        (UINTN)Device,
+        (UINTN)Func,
+        PciIoDevice->SystemPageSize
+        ));
+      //
+      // Adjust SystemPageSize for Alignment usage later
+      //
+      PciIoDevice->SystemPageSize <<= 12;
+
+      //
+      // Calculate BusReservation for PCI IOV
+      //
+
+      //
+      // Read First FirstVFOffset, InitialVFs, and VFStride
+      //
+      PciIo->Pci.Read (
+                   PciIo,
+                   EfiPciIoWidthUint16,
+                   PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF,
+                   1,
+                   &FirstVFOffset
+                   );
+      DEBUG ((
+        EFI_D_INFO,
+        "PCI SR-IOV B%x.D%x.F%x - FirstVFOffset - 0x%x\n",
+        (UINTN)Bus,
+        (UINTN)Device,
+        (UINTN)Func,
+        (UINTN)FirstVFOffset
+        ));
+
+      PciIo->Pci.Read (
+                   PciIo,
+                   EfiPciIoWidthUint16,
+                   PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS,
+                   1,
+                   &PciIoDevice->InitialVFs
+                   );
+      DEBUG ((
+        EFI_D_INFO,
+        "PCI SR-IOV B%x.D%x.F%x - InitialVFs - 0x%x\n",
+        (UINTN)Bus,
+        (UINTN)Device,
+        (UINTN)Func,
+        (UINTN)PciIoDevice->InitialVFs
+        ));
+
+      PciIo->Pci.Read (
+                   PciIo,
+                   EfiPciIoWidthUint16,
+                   PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE,
+                   1,
+                   &VFStride
+                   );
+      DEBUG ((
+        EFI_D_INFO,
+        "PCI SR-IOV B%x.D%x.F%x - VFStride - 0x%x\n",
+        (UINTN)Bus,
+        (UINTN)Device,
+        (UINTN)Func,
+        (UINTN)VFStride
+        ));
+
+      //
+      // Calculate LastVF
+      //
+      PFRid = EFI_PCI_RID(Bus, Device, Func);
+      LastVF = PFRid + FirstVFOffset + (PciIoDevice->InitialVFs - 1) * VFStride;
+
+      //
+      // Calculate ReservedBusNum for this PF
+      //
+      PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID (LastVF) - Bus + 1);
+      DEBUG ((
+        EFI_D_INFO,
+        "PCI SR-IOV B%x.D%x.F%x - reserved bus number - 0x%x\n",
+        (UINTN)Bus,
+        (UINTN)Device,
+        (UINTN)Func,
+        (UINTN)PciIoDevice->ReservedBusNum
+        ));
+
+      DEBUG ((
+        EFI_D_INFO,
+        "PCI SR-IOV B%x.D%x.F%x - SRIOV Cap offset - 0x%x\n",
+        (UINTN)Bus,
+        (UINTN)Device,
+        (UINTN)Func,
+        (UINTN)PciIoDevice->SrIovCapabilityOffset
+        ));
+    }
   }
 
-  // Calculate BusReservation for PCI IOV
-  //
-  if ((PciIoDevice->SrIovCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {
-    UINT16    VFStride;
-    UINT16    FirstVFOffset;
-    UINT32    PFRid;
-    UINT32    LastVF;
-
-    //
-    // Read First FirstVFOffset, InitialVFs, and VFStride
-    //
-    PciIo->Pci.Read (
-                 PciIo,
-                 EfiPciIoWidthUint16,
-                 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF,
-                 1,
-                 &FirstVFOffset
-                 );
-    DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - FirstVFOffset - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)FirstVFOffset));
-
-    PciIo->Pci.Read (
-                 PciIo,
-                 EfiPciIoWidthUint16,
-                 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS,
-                 1,
-                 &PciIoDevice->InitialVFs
-                 );
-    DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - InitialVFs - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)PciIoDevice->InitialVFs));
-
-    PciIo->Pci.Read (
-                 PciIo,
-                 EfiPciIoWidthUint16,
-                 PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE,
-                 1,
-                 &VFStride
-                 );
-    DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - VFStride - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)VFStride));
-
-    //
-    // Calculate LastVF
-    //
-    PFRid = EFI_PCI_RID(Bus, Device, Func);
-    LastVF = PFRid + FirstVFOffset + (PciIoDevice->InitialVFs - 1) * VFStride;
-
-    //
-    // Calculate ReservedBusNum for this PF
-    //
-    PciIoDevice->ReservedBusNum = (UINT16)(EFI_PCI_BUS_OF_RID (LastVF) - Bus + 1);
-    DEBUG ((EFI_D_INFO, "PCI-IOV B%x.D%x.F%x - reserved bus number - 0x%x\n", (UINTN)Bus, (UINTN)Device, (UINTN)Func, (UINTN)PciIoDevice->ReservedBusNum));
+  if (PcdGetBool (PcdMrIovSupport)) {
+    Status = LocatePciExpressCapabilityRegBlock (
+               PciIoDevice,
+               EFI_PCIE_CAPABILITY_ID_MRIOV,
+               &PciIoDevice->MrIovCapabilityOffset,
+               NULL
+               );
+    if (!EFI_ERROR (Status)) {
+      DEBUG ((
+        EFI_D_INFO,
+        "PCI MR-IOV B%x.D%x.F%x - MRIOV Cap offset - 0x%x\n",
+        (UINTN)Bus,
+        (UINTN)Device,
+        (UINTN)Func,
+        (UINTN)PciIoDevice->MrIovCapabilityOffset
+        ));
+    }
   }
 
-
   //
   // Initialize the reserved resource list
   //
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h
index fa3a3992fd..a4489b895f 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h
@@ -1,7 +1,7 @@
 /** @file
   PCI emumeration support functions declaration for PCI Bus module.
 
-Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials
 are licensed and made available under the terms and conditions of the BSD License
 which accompanies this distribution.  The full text of the license may be found at
@@ -364,7 +364,7 @@ InitializeP2C (
   Create and initiliaze general PCI I/O device instance for
   PCI device/bridge device/hotplug bridge device.
 
-  @param PciRootBridgeIo   Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+  @param Bridge            Parent bridge instance.
   @param Pci               Input Pci information block.
   @param Bus               Device Bus NO.
   @param Device            Device device NO.
@@ -375,7 +375,7 @@ InitializeP2C (
 **/
 PCI_IO_DEVICE *
 CreatePciIoDevice (
-  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,
+  IN PCI_IO_DEVICE                    *Bridge,
   IN PCI_TYPE00                       *Pci,
   IN UINT8                            Bus,
   IN UINT8                            Device,
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
index 8397a40582..4717140255 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
@@ -1,7 +1,7 @@
 /** @file
   Internal library implementation for PCI Bus module.
 
-Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials
 are licensed and made available under the terms and conditions of the BSD License
 which accompanies this distribution.  The full text of the license may be found at
@@ -738,50 +738,43 @@ PciScanBus (
                 );
 
       if (EFI_ERROR (Status)) {
-        if (Func == 0) {
-          //
-          // Skip sub functions, this is not a multi function device
-          //
-          Func = PCI_MAX_FUNC;
-        }
-
         continue;
       }
 
       DEBUG((EFI_D_INFO, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber, Device, Func ));
 
+      //
+      // Get the PCI device information
+      //
+      Status = PciSearchDevice (
+                Bridge,
+                &Pci,
+                StartBusNumber,
+                Device,
+                Func,
+                &PciDevice
+                );
+
+      ASSERT (!EFI_ERROR (Status));
+
+      PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);
+
+      if (!IS_PCI_BRIDGE (&Pci)) {
+        //
+        // PCI bridges will be called later
+        // Here just need for PCI device or PCI to cardbus controller
+        // EfiPciBeforeChildBusEnumeration for PCI Device Node
+        //
+        PreprocessController (
+            PciDevice,
+            PciDevice->BusNumber,
+            PciDevice->DeviceNumber,
+            PciDevice->FunctionNumber,
+            EfiPciBeforeChildBusEnumeration
+            );
+      }
+
       if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
-        //
-        // Get the PCI device information
-        //
-        Status = PciSearchDevice (
-                  Bridge,
-                  &Pci,
-                  StartBusNumber,
-                  Device,
-                  Func,
-                  &PciDevice
-                  );
-
-        ASSERT (!EFI_ERROR (Status));
-
-        PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);
-
-        if (!IS_PCI_BRIDGE (&Pci)) {
-          //
-          // PCI bridges will be called later
-          // Here just need for PCI device or PCI to cardbus controller
-          // EfiPciBeforeChildBusEnumeration for PCI Device Node
-          //
-          PreprocessController (
-              PciDevice,
-              PciDevice->BusNumber,
-              PciDevice->DeviceNumber,
-              PciDevice->FunctionNumber,
-              EfiPciBeforeChildBusEnumeration
-              );
-        }
-
         //
         // For Pci Hotplug controller devcie only
         //
@@ -976,18 +969,9 @@ PciScanBus (
       } else  {
         //
         // It is device. Check PCI IOV for Bus reservation
-        //
-        if (PciDevice == NULL) {
-          //
-          // No PciDevice found, conitue Scan
-          //
-          continue;
-        }
-        //
         // Go through each function, just reserve the MAX ReservedBusNum for one device
         //
-        if ((PciDevice->AriCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport)& EFI_PCI_IOV_POLICY_SRIOV) != 0)) {
-
+        if (PcdGetBool (PcdSrIovSupport) && PciDevice->SrIovCapabilityOffset != 0) {
           if (TempReservedBusNum < PciDevice->ReservedBusNum) {
 
             (*SubBusNumber) = (UINT8)((*SubBusNumber) + PciDevice->ReservedBusNum - TempReservedBusNum);