public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] New PCI features - MPS, MRRS, RO, NS, CTO
@ 2019-11-01 15:09 Javeed, Ashraf
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe:New PCI features separation with PCD Javeed, Ashraf
                   ` (23 more replies)
  0 siblings, 24 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-01 15:09 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

The EDK2 Kernel PciBusDxe driver is enhanced to enable the configuration
of PCI features like
(1) Max_Payload_Size
(2) Max_Read_Req_Size
(3) Relax Ordering
(4) No-Snoop
(5) Completion Timeout

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).

Relax Ordering:- The PCI Device Control register has the enabling of
Relax Ordering functionality register field (bit 4). If this bit is Set,
the PCI Function is permitted to set the Relaxed Ordering bit in the
Attributes field of transactions it initiates that do not require strong
write ordering (see PCI Base Specification 4, Section 2.2.6.4 and Sect-
ion 2.4). Any supporting PCI function is expected have this bit enabled
by as per its hardware default; the code enhancement is to enable / dis-
able as per the PCI device policy provided by the platform firmware. If
no device policy override is provided than it shall be ignored by the PCI
Bus driver for that PCI function.

No-Snoop:- The PCI Device Control register has the enabling of No-Snoop
functionality register field (bit 11). If this bit is Set, the PCI
Function is permitted to Set the No Snoop bit in the Requester Attributes
of transactions it initiates that do not require hardware enforced cache
coherency (see PCI Base Specification 4, Section 2.2.6.5). Any supporting
PCI function is expected have this bit enabled by as per its hardware
default; the code enhancement is to enable / disable as per the PCI
device policy provided by the platform firmware. If no device policy
override is provided than it shall be ignored by the PCI Bus driver for
that PCI function.

Completion Timeout:- The PCI Device Control 2 register provides two
register fields based on its Device Capability 2 register; the CTO Ranges
(bits [3:0]) and the disabling of CTO detection mechanism (bit 4). The
software is permitted to change the CTO ranges and enable/disable the CTO
detection mechanism any time. The code enhancement here is to override
these register fields as per the platform device policy. If no device
policy override is provided than it shall be ignored by the PCI Bus
driver for that PCI function.

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>
---

Ashraf Javeed (12):
  MdeModulePkg/PciBusDxe:New PCI features separation with PCD
  PciBusDxe: Reorganize the PCI Platform Protocol usage code
  PciBusDxe: Separation of the PCI device registration and start
  PciBusDxe: Inclusion of new PCI Platform Protocol 2
  PciBusDxe: Setup sub-phases for PCI feature enumeration
  PciBusDxe: Integration of setup for PCI feature enumeration
  PciBusDxe: Record the PCI-Express Capability Structure
  PciBusDxe: New PCI feature Max_Payload_Size
  PciBusDxe: New PCI feature Max_Read_Req_Size
  PciBusDxe: New PCI feature Relax Ordering
  PciBusDxe: New PCI feature No-Snoop
  PciBusDxe: New PCI feature Completion Timeout

 MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c               |   23 +----------
 MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h               |   20 ++++++++--
 MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf          |    9 ++++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c     |  233 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------
 MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c        |  139 ++++++++++++++++-------------------------------------------------
 MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c |   34 ++++++++++------
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c    | 2030 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h    |  223 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c   |  749 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h   |  191 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c   |   15 +------
 MdeModulePkg/MdeModulePkg.dec                         |   22 +++++++++++
 12 files changed, 3450 insertions(+), 238 deletions(-)
 create mode 100644 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
 create mode 100644 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
 create mode 100644 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
 create mode 100644 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h

-- 
2.21.0.windows.1


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

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe:New PCI features separation with PCD
  2019-11-01 15:09 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] New PCI features - MPS, MRRS, RO, NS, CTO Javeed, Ashraf
@ 2019-11-01 15:09 ` Javeed, Ashraf
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12] PciBusDxe: Reorganize the PCI Platform Protocol usage code Javeed, Ashraf
                   ` (22 subsequent siblings)
  23 siblings, 0 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-01 15:09 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

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

Definition of bit masks for the new PCD for the following new PCI feature
set:-
1.	Maximum Payload Size (MPS)
2.	Maximum Read Request Size (MRRS)
3.	Completion Timeout (CTO)
4.	Relax Order (RO) Enable
5.	No Snoop (NS) Enable
6.	Extended Tag
7.	ASPM support
8.	Common Clock Configuration
9.	Extended SYNC
10.	Atomic Op
11.	LTR Enable
12.	PTM support

Code changes made to the PCI Bus driver to adopt to these new PCD defini-
tion, helper routines defined for features that needs to be supported in.
future.

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/PciBusDxe.inf       |   5 ++++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h |  26 ++++++++++++++++++++++++++
 MdeModulePkg/MdeModulePkg.dec                      |  22 ++++++++++++++++++++++
 4 files changed, 229 insertions(+), 1 deletion(-)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
index 05c2202..6dab970 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,8 @@
   PciCommand.h
   PciIo.h
   PciBus.h
+  PciFeatureSupport.c
+  PciFeatureSupport.h
 
 [Packages]
   MdePkg/MdePkg.dec
@@ -104,6 +106,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/PciFeatureSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
new file mode 100644
index 0000000..8be227a
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -0,0 +1,177 @@
+/** @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 "PciBus.h"
+#include "PciFeatureSupport.h"
+
+/**
+  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;
+}
+
+/**
+  Main routine to indicate whether the platform has selected the Relax Ordering
+  PCI feature to be configured by this driver
+
+  @retval TRUE    platform has selected the Relax Ordering to be configured
+          FALSE   platform has not selected this feature
+**/
+BOOLEAN
+SetupRelaxOrder (
+  )
+{
+  return (PcdGet32 (PcdOtherPciFeatures) & PCI_FEATURE_SUPPORT_FLAG_RO) ? TRUE : FALSE;
+}
+
+/**
+  Main routine to indicate whether the platform has selected the No-Snoop
+  PCI feature to be configured by this driver
+
+  @retval TRUE    platform has selected the No-Snoop to be configured
+          FALSE   platform has not selected this feature
+**/
+BOOLEAN
+SetupNoSnoop (
+  )
+{
+  return (PcdGet32 (PcdOtherPciFeatures) & PCI_FEATURE_SUPPORT_FLAG_NS) ? TRUE : FALSE;
+}
+
+/**
+  Main routine to indicate whether the platform has selected the Completion Timeout
+  PCI feature to be configured by this driver
+
+  @retval TRUE    platform has selected the Completion Timeout to be configured
+          FALSE   platform has not selected this feature
+**/
+BOOLEAN
+SetupCompletionTimeout (
+  )
+{
+  return (PcdGet32 (PcdOtherPciFeatures) & PCI_FEATURE_SUPPORT_FLAG_CTO) ? TRUE : FALSE;
+}
+
+/**
+  Main routine to indicate whether the platform has selected the Extended Tag
+  PCI feature to be configured by this driver
+
+  @retval TRUE    platform has selected the Completion Timeout to be configured
+          FALSE   platform has not selected this feature
+**/
+BOOLEAN
+SetupExtendedTag (
+  )
+{
+  return (PcdGet32 (PcdOtherPciFeatures) & PCI_FEATURE_SUPPORT_FLAG_ETAG) ? TRUE : FALSE;
+}
+
+/**
+  Main routine to indicate whether the platform has selected the Atomic Op
+  PCI feature to be configured by this driver
+
+  @retval TRUE    platform has selected the Completion Timeout to be configured
+          FALSE   platform has not selected this feature
+**/
+BOOLEAN
+SetupAtomicOp (
+  )
+{
+  return (PcdGet32 (PcdOtherPciFeatures) & PCI_FEATURE_SUPPORT_FLAG_AOP) ? TRUE : FALSE;
+}
+/**
+  Main routine to indicate whether the platform has selected the LTR
+  PCI feature to be configured by this driver
+
+  @retval TRUE    platform has selected the Completion Timeout to be configured
+          FALSE   platform has not selected this feature
+**/
+BOOLEAN
+SetupLtr (
+  )
+{
+  return (PcdGet32 (PcdOtherPciFeatures) & PCI_FEATURE_SUPPORT_FLAG_LTR) ? TRUE : FALSE;
+}
+
+/**
+  Main routine to indicate whether the platform has selected the ASPM state
+  PCI feature to be configured by this driver
+
+  @retval TRUE    platform has selected the Completion Timeout to be configured
+          FALSE   platform has not selected this feature
+**/
+BOOLEAN
+SetupAspm (
+  )
+{
+  return (PcdGet32 (PcdOtherPciFeatures) & PCI_FEATURE_SUPPORT_FLAG_ASPM) ? TRUE : FALSE;
+}
+
+/**
+  Main routine to indicate whether the platform has selected the Common Clock Configuration
+  PCI feature to be configured by this driver
+
+  @retval TRUE    platform has selected the Completion Timeout to be configured
+          FALSE   platform has not selected this feature
+**/
+BOOLEAN
+SetupCommonClkCfg (
+  )
+{
+  return (PcdGet32 (PcdOtherPciFeatures) & PCI_FEATURE_SUPPORT_FLAG_CCC) ? TRUE : FALSE;
+}
+
+/**
+  Main routine to indicate whether the platform has selected the Extended Synch
+  PCI feature to be configured by this driver
+
+  @retval TRUE    platform has selected the Completion Timeout to be configured
+          FALSE   platform has not selected this feature
+**/
+BOOLEAN
+SetupExtendedSynch (
+  )
+{
+  return (PcdGet32 (PcdOtherPciFeatures) & PCI_FEATURE_SUPPORT_FLAG_ESYN) ? TRUE : FALSE;
+}
+
+/**
+  Main routine to indicate whether the platform has selected the PIM Control
+  PCI feature to be configured by this driver
+
+  @retval TRUE    platform has selected the Completion Timeout to be configured
+          FALSE   platform has not selected this feature
+**/
+BOOLEAN
+SetupPtm (
+  )
+{
+  return (PcdGet32 (PcdOtherPciFeatures) & PCI_FEATURE_SUPPORT_FLAG_PTM) ? TRUE : FALSE;
+}
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
new file mode 100644
index 0000000..d06a5e8
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
@@ -0,0 +1,26 @@
+/** @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_
+//
+// Macro definitions for the PCI Features support PCD
+//
+#define PCI_FEATURE_SUPPORT_FLAG_MPS  BIT0
+#define PCI_FEATURE_SUPPORT_FLAG_MRRS BIT1
+#define PCI_FEATURE_SUPPORT_FLAG_RO   BIT2
+#define PCI_FEATURE_SUPPORT_FLAG_NS   BIT3
+#define PCI_FEATURE_SUPPORT_FLAG_CTO  BIT4
+#define PCI_FEATURE_SUPPORT_FLAG_ETAG BIT5
+#define PCI_FEATURE_SUPPORT_FLAG_AOP  BIT6
+#define PCI_FEATURE_SUPPORT_FLAG_LTR  BIT7
+#define PCI_FEATURE_SUPPORT_FLAG_ASPM BIT12
+#define PCI_FEATURE_SUPPORT_FLAG_CCC  BIT13
+#define PCI_FEATURE_SUPPORT_FLAG_ESYN BIT14
+#define PCI_FEATURE_SUPPORT_FLAG_PTM  BIT20
+#endif
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 12e0bbf..ed82e85 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -1036,6 +1036,28 @@
   # @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 - if set, the PCI Bus driver programs the device's Relax Ordering state.<BR>
+  #   Bit 3 - if set, the PCI Bus driver programs the device's No-Snoop state.<BR>
+  #   Bit 4 - if set, the PCI Bus driver programs the device's Completion Timeout range.<BR>
+  #   Bit 5 - if set, the PCI Bus driver programs the device's Extended Tag range.<BR>
+  #   Bit 6 - if set, the PCI Bus driver programs the device's AtomicOp feature.<BR>
+  #   Bit 7 - if set, the PCI Bus driver programs the device's LTR feature.<BR>
+  #   Bit 8 to 11 - Reserved for future use by the PCI Bus driver.<BR>
+  #   Bit 12 - if set, the PCI Bus driver programs the PCIe link ASPM state.<BR>
+  #   Bit 13 - if set, the PCI Bus driver programs the PCIe link Common Clock Configuration.<BR>
+  #   Bit 14 - if set, the PCI Bus driver programs the PCIe link Extended Synch state.<BR>
+  #   Bit 15 to 19 - Reserved for future use by the PCI Bus driver.<BR>
+  #   Bit 20 - if set, the PCI Bus driver programs the device's PTM feature.<BR>
+  #   Bit 21 to 31 - Reserved for future use by the PCI Bus driver.<BR>
+  # @Prompt The UEFI PCI Bus driver enables the new set of other PCI Features.
+  gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures|0x001070FF|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] 51+ messages in thread

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12] PciBusDxe: Reorganize the PCI Platform Protocol usage code
  2019-11-01 15:09 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] New PCI features - MPS, MRRS, RO, NS, CTO Javeed, Ashraf
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe:New PCI features separation with PCD Javeed, Ashraf
@ 2019-11-01 15:09 ` Javeed, Ashraf
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12] PciBusDxe: Separation of the PCI device registration and start Javeed, Ashraf
                   ` (21 subsequent siblings)
  23 siblings, 0 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-01 15:09 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

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

The following legacy PCI Platform Protocol usage is reorganized in the
separate source files:-
(1) PlatformPrepController
(2) PlatformNotify
(3) GetPlatformPolicy
(4) GetPciRom

This code changes are made to support the new PCI Platform Protocol along
with the existing legacy interface in the PCI Bus driver.

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             |   3 +--
 MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf        |   2 ++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c   |  58 +++++++++++-----------------------------------------------
 MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c      | 139 +++++++++++++++++++++++++++++++++----------------------------------------------------------------------------------------------------------
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 254 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c |  15 +--------------
 8 files changed, 413 insertions(+), 190 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
index b020ce5..45cd64d 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
-          );
-  }
+  LocatePciPlatformProtocol ();
 
   if (mIoMmuProtocol == NULL) {
     gBS->LocateProtocol (
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index 504a1b1..141c158 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -79,6 +79,7 @@ typedef enum {
 #include "PciPowerManagement.h"
 #include "PciHotPlugSupport.h"
 #include "PciLib.h"
+#include "PciPlatformSupport.h"
 
 #define VGABASE1  0x3B0
 #define VGALIMIT1 0x3BB
@@ -307,8 +308,6 @@ extern UINTN                                        gPciHostBridgeNumber;
 extern EFI_HANDLE                                   gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM];
 extern UINT64                                       gAllOne;
 extern UINT64                                       gAllZero;
-extern EFI_PCI_PLATFORM_PROTOCOL                    *gPciPlatformProtocol;
-extern EFI_PCI_OVERRIDE_PROTOCOL                    *gPciOverrideProtocol;
 extern BOOLEAN                                      mReserveIsaAliases;
 extern BOOLEAN                                      mReserveVgaAliases;
 
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
index 6dab970..4ce99ce 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
@@ -59,6 +59,8 @@
   PciBus.h
   PciFeatureSupport.c
   PciFeatureSupport.h
+  PciPlatformSupport.c
+  PciPlatformSupport.h
 
 [Packages]
   MdePkg/MdePkg.dec
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
index b7832c6..149a120 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
@@ -208,8 +208,6 @@ RegisterPciDevice (
   )
 {
   EFI_STATUS          Status;
-  VOID                *PlatformOpRomBuffer;
-  UINTN               PlatformOpRomSize;
   EFI_PCI_IO_PROTOCOL *PciIo;
   UINT8               Data8;
   BOOLEAN             HasEfiImage;
@@ -244,49 +242,16 @@ 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 +259,7 @@ RegisterPciDevice (
           PciIoDevice->FunctionNumber,
           PciIoDevice->PciIo.RomImage,
           PciIoDevice->PciIo.RomSize
-          );
-      }
+        );
     }
   }
 
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
index 8db1ebf..aef8a3b 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/PciPlatformSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
new file mode 100644
index 0000000..6f95794
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
@@ -0,0 +1,254 @@
+/** @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 "PciBus.h"
+
+EFI_PCI_PLATFORM_PROTOCOL                     *mPciPlatformProtocol;
+EFI_PCI_OVERRIDE_PROTOCOL                     *mPciOverrideProtocol;
+
+
+
+/**
+  This function retrieves the PCI Platform Protocol published by platform driver
+
+**/
+VOID
+LocatePciPlatformProtocol (
+  )
+{
+    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 (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 (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 (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 (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 (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;
+}
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
new file mode 100644
index 0000000..c0d3b49
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
@@ -0,0 +1,109 @@
+/** @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_
+
+/**
+  This function retrieves the PCI Platform Protocol published by platform driver
+
+**/
+VOID
+LocatePciPlatformProtocol (
+  );
+
+/**
+  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
+  );
+
+#endif
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
index 4969ee0..be6f42a 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;
-- 
2.21.0.windows.1


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

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12] PciBusDxe: Separation of the PCI device registration and start
  2019-11-01 15:09 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] New PCI features - MPS, MRRS, RO, NS, CTO Javeed, Ashraf
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe:New PCI features separation with PCD Javeed, Ashraf
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12] PciBusDxe: Reorganize the PCI Platform Protocol usage code Javeed, Ashraf
@ 2019-11-01 15:09 ` Javeed, Ashraf
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 04/12] PciBusDxe: Inclusion of new PCI Platform Protocol 2 Javeed, Ashraf
                   ` (20 subsequent siblings)
  23 siblings, 0 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-01 15:09 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

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

The separation of the PCI device registration phase includes only the
installation of the PCI IO Protocol on the PCI node to acquire the EFI
handles, and loading of its applicable PCI Option ROM.

The separation of the PCI device start phase only includes the code that
enables the PCI Bridge device as a Bus Master.

This code change is made in order to introduce the enabling of the other
PCI features in the PCI Bus driver.

Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
---
 MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------
 1 file changed, 130 insertions(+), 34 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
index 149a120..33a0e94 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
@@ -561,7 +561,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.
@@ -576,7 +576,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,
@@ -590,7 +665,6 @@ StartPciDevicesOnBridge (
   EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;
   EFI_STATUS                Status;
   LIST_ENTRY                *CurrentLink;
-  UINT64                    Supports;
 
   PciIoDevice = NULL;
   CurrentLink = RootBridge->ChildList.ForwardLink;
@@ -645,7 +719,7 @@ StartPciDevicesOnBridge (
       // If it is a PPB
       //
       if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
-        Status = StartPciDevicesOnBridge (
+        Status = RegisterPciDevicesOnBridge (
                    Controller,
                    PciIoDevice,
                    CurrentDevicePath,
@@ -653,20 +727,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 {
 
@@ -697,28 +757,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;
@@ -732,6 +777,57 @@ 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 {
+    //
+    // 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.
-- 
2.21.0.windows.1


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

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 04/12] PciBusDxe: Inclusion of new PCI Platform Protocol 2
  2019-11-01 15:09 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] New PCI features - MPS, MRRS, RO, NS, CTO Javeed, Ashraf
                   ` (2 preceding siblings ...)
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12] PciBusDxe: Separation of the PCI device registration and start Javeed, Ashraf
@ 2019-11-01 15:09 ` Javeed, Ashraf
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration Javeed, Ashraf
                   ` (19 subsequent siblings)
  23 siblings, 0 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-01 15:09 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

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

The code changes are made to support the new PCI Platform Protocol, as
well as the legacy PCI Platform Protocol interfaces.

The code change is made to consume the new interface to acquire the PCI
device-specific platform policy.

This code change is made to support the enabling of the other
PCI features in the PCI Bus driver.

Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
---
 MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h             |   2 ++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf        |   2 ++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 208 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h |  18 ++++++++++++++++++
 4 files changed, 228 insertions(+), 2 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index 141c158..95a677b 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>
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
index 4ce99ce..44dec53 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
@@ -95,6 +95,8 @@
   gEfiLoadFile2ProtocolGuid                       ## SOMETIMES_PRODUCES
   gEdkiiIoMmuProtocolGuid                         ## SOMETIMES_CONSUMES
   gEfiLoadedImageDevicePathProtocolGuid           ## CONSUMES
+  gEfiPciPlatformProtocol2Guid                     ## SOMETIMES_CONSUMES
+  gEfiPciOverrideProtocol2Guid                     ## SOMETIMES_CONSUMES
 
 [FeaturePcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport      ## CONSUMES
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
index 6f95794..238959e 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
@@ -14,6 +14,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 EFI_PCI_PLATFORM_PROTOCOL                     *mPciPlatformProtocol;
 EFI_PCI_OVERRIDE_PROTOCOL                     *mPciOverrideProtocol;
 
+EFI_PCI_PLATFORM_PROTOCOL2                    *mPciPlatformProtocol2;
+EFI_PCI_OVERRIDE_PROTOCOL2                    *mPciOverrideProtocol2;
 
 
 /**
@@ -24,6 +26,29 @@ VOID
 LocatePciPlatformProtocol (
   )
 {
+  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,
@@ -42,6 +67,7 @@ LocatePciPlatformProtocol (
           (VOID **) &mPciOverrideProtocol
       );
     }
+  }
 }
 
 /**
@@ -52,13 +78,17 @@ 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;
 }
 
@@ -90,6 +120,32 @@ PciPlatformPreprocessController (
   )
 {
   EFI_STATUS  Status;
+
+  if (mPciPlatformProtocol2 != NULL) {
+    //
+    // Call PlatformPci::PrepController() if the protocol is present.
+    //
+    Status = mPciPlatformProtocol2->PlatformPrepController (
+                                      mPciPlatformProtocol2,
+                                      HostBridgeHandle,
+                                      RootBridgeHandle,
+                                      RootBridgePciAddress,
+                                      Phase,
+                                      ExecPhase
+                                    );
+  } else if (mPciOverrideProtocol2 != NULL) {
+    //
+    // Call PlatformPci::PrepController() if the protocol is present.
+    //
+    Status = mPciOverrideProtocol2->PlatformPrepController (
+                                      mPciOverrideProtocol2,
+                                      HostBridgeHandle,
+                                      RootBridgeHandle,
+                                      RootBridgePciAddress,
+                                      Phase,
+                                      ExecPhase
+                                    );
+  } else {
     if (mPciPlatformProtocol != NULL) {
       //
       // Call PlatformPci::PrepController() if the protocol is present.
@@ -120,6 +176,7 @@ PciPlatformPreprocessController (
       //
       return EFI_NOT_FOUND;
     }
+  }
   return Status;
 }
 
@@ -142,6 +199,21 @@ PciPlatformNotifyPhase (
 {
   EFI_STATUS  Status;
 
+  if (mPciPlatformProtocol2 != NULL) {
+    Status = mPciPlatformProtocol2->PlatformNotify (
+                                      mPciPlatformProtocol2,
+                                      HostBridgeHandle,
+                                      Phase,
+                                      ExecPhase
+                                    );
+  } else if (mPciOverrideProtocol2 != NULL) {
+    Status = mPciOverrideProtocol2->PlatformNotify (
+                                      mPciOverrideProtocol2,
+                                      HostBridgeHandle,
+                                      Phase,
+                                      ExecPhase
+                                    );
+  } else {
 
     if (mPciPlatformProtocol != NULL) {
       Status = mPciPlatformProtocol->PlatformNotify (
@@ -163,6 +235,7 @@ PciPlatformNotifyPhase (
       //
       return EFI_NOT_FOUND;
     }
+  }
   return Status;
 }
 
@@ -179,6 +252,18 @@ PciGetPlatformPolicy (
   )
 {
   EFI_STATUS  Status;
+
+  if (mPciPlatformProtocol2 != NULL) {
+      Status = mPciPlatformProtocol2->GetPlatformPolicy (
+                                        mPciPlatformProtocol2,
+                                        PciPolicy
+                                      );
+  } else if (mPciOverrideProtocol2 != NULL) {
+      Status = mPciOverrideProtocol2->GetPlatformPolicy (
+                                        mPciOverrideProtocol2,
+                                        PciPolicy
+                                      );
+  } else {
     if (mPciPlatformProtocol != NULL) {
       Status = mPciPlatformProtocol->GetPlatformPolicy (
                                       mPciPlatformProtocol,
@@ -197,6 +282,7 @@ PciGetPlatformPolicy (
       //
       return EFI_NOT_FOUND;
     }
+  }
   return Status;
 }
 
@@ -223,6 +309,22 @@ GetPlatformPciOptionRom (
   EFI_STATUS  Status;
   VOID        *PlatformOpRomBuffer;
   UINTN       PlatformOpRomSize;
+
+  if (mPciPlatformProtocol2 != NULL) {
+    Status = mPciPlatformProtocol2->GetPciRom (
+                                      mPciPlatformProtocol2,
+                                      PciIoDevice->Handle,
+                                      &PlatformOpRomBuffer,
+                                      &PlatformOpRomSize
+                                      );
+  } else if (mPciOverrideProtocol2 != NULL) {
+    Status = mPciOverrideProtocol2->GetPciRom (
+                                      mPciOverrideProtocol2,
+                                      PciIoDevice->Handle,
+                                      &PlatformOpRomBuffer,
+                                      &PlatformOpRomSize
+                                      );
+  } else {
     if (mPciPlatformProtocol != NULL) {
       Status = mPciPlatformProtocol->GetPciRom (
                                       mPciPlatformProtocol,
@@ -243,6 +345,7 @@ GetPlatformPciOptionRom (
       //
       return EFI_NOT_FOUND;
     }
+  }
 
   if (!EFI_ERROR (Status)) {
     PciIoDevice->EmbeddedRom    = FALSE;
@@ -252,3 +355,104 @@ GetPlatformPciOptionRom (
   }
   return Status;
 }
+
+/**
+  Generic routine to setup the PCI features as per its predetermined defaults.
+**/
+VOID
+SetupDefaultsDevicePlatformPolicy (
+  IN  PCI_IO_DEVICE               *PciDevice
+  )
+{
+}
+
+/**
+  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
+                                  );
+  switch (Status) {
+    case  EFI_SUCCESS:
+      //
+      // platform chipset policies are returned for this PCI device
+      //
+
+      DEBUG ((
+          DEBUG_INFO, "[device policy: platform]"
+      ));
+      return Status;
+
+    case  EFI_UNSUPPORTED:
+      //
+      // platform chipset policies are not provided for this PCI device
+      // let the enumeration happen as per the PCI standard way
+      //
+      SetupDefaultsDevicePlatformPolicy (PciIoDevice);
+      DEBUG ((
+          DEBUG_INFO, "[device policy: default]"
+      ));
+      return EFI_SUCCESS;
+
+    default:
+      DEBUG ((
+          DEBUG_ERROR, "[device policy: none (error)]"
+      ));
+      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
index c0d3b49..a13131c 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
@@ -106,4 +106,22 @@ GetPlatformPciOptionRom (
   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
+  );
 #endif
-- 
2.21.0.windows.1


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

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
  2019-11-01 15:09 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] New PCI features - MPS, MRRS, RO, NS, CTO Javeed, Ashraf
                   ` (3 preceding siblings ...)
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 04/12] PciBusDxe: Inclusion of new PCI Platform Protocol 2 Javeed, Ashraf
@ 2019-11-01 15:09 ` Javeed, Ashraf
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 06/12] PciBusDxe: Integration of setup " Javeed, Ashraf
                   ` (18 subsequent siblings)
  23 siblings, 0 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-01 15:09 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

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

The code changes are made to setup the following internal sub-phases for
enumerating the PCI features in the late phase of the PCI Bus driver.
(1) PciFeatureRootBridgeScan - initial phase in configuring the other PCI
    features to record the primary root ports
(2) PciFeatureGetDevicePolicy - get the PCI device-specific platform pol-
    icies and align with device capabilities
(3) PciFeatureSetupPhase - align all PCI nodes in the PCI heirarchical
    tree (if required for that PCI feature)
(4) PciFeatureConfigurationPhase - finally override to complete configu-
    ration of the PCI feature

The code changes are made to support the configuration of other PCIe
features, like MPS, which require a common value to be assigned among
all the child PCI devices and its parent root port device.

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/PciFeatureSupport.c | 859 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1005 insertions(+)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
index 8be227a..ab0e096 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -9,6 +9,23 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include "PciBus.h"
 #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 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 whether the platform has selected the Max_Payload_Size
   PCI feature to be configured by this driver
@@ -175,3 +192,845 @@ SetupPtm (
 {
   return (PcdGet32 (PcdOtherPciFeatures) & PCI_FEATURE_SUPPORT_FLAG_PTM) ? TRUE : FALSE;
 }
+
+/**
+ Helper routine to determine the existence of previously enumerated PCI device
+
+ @retval  TRUE  PCI device exist
+          FALSE does not exist
+**/
+BOOLEAN
+DeviceExist (
+  PCI_IO_DEVICE                   *PciDevice
+  )
+{
+  EFI_PCI_IO_PROTOCOL   *PciIoProtocol = &PciDevice->PciIo;
+  UINT16                VendorId = 0xFFFF;
+
+  PciIoProtocol->Pci.Read (
+                      PciIoProtocol,
+                      EfiPciIoWidthUint16,
+                      PCI_VENDOR_ID_OFFSET,
+                      1,
+                      &VendorId
+                      );
+  if (VendorId == 0 || VendorId == 0xFFFF) {
+    return FALSE;
+  } else {
+    return TRUE;
+  }
+}
+
+/**
+  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 == NULL) {
+      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->OtherPciFeaturesConfigurationTable);
+      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->OtherPciFeaturesConfigurationTable);
+        FreePool (Temp);
+      } while (!IsListEmpty (Link));
+      FreePool (mPrimaryRootPortList->OtherPciFeaturesConfigurationTable);
+      FreePool (mPrimaryRootPortList);
+    }
+    mPrimaryRootPortList = 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 ();
+  }
+}
+
+/**
+  Main routine to determine the child PCI devices of a PCI bridge device
+  and group them under a common internal PCI features Configuration table.
+
+  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
+  @param  PciFeaturesConfigTable          A pointer to a pointer to the
+                                          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 PCI bus range (not a child)
+
+  @retval EFI_SUCCESS                     able to determine the PCI feature
+                                          configuration table. For RCiEP since
+                                          since it is not prepared.
+          EFI_DEVICE_ERROR                the PCI device has invalid EFI device
+                                          path
+**/
+EFI_STATUS
+GetPciFeaturesConfigurationTable (
+  IN  PCI_IO_DEVICE                           *PciDevice,
+  OUT OTHER_PCI_FEATURES_CONFIGURATION_TABLE  **PciFeaturesConfigTable
+  )
+{
+  LIST_ENTRY                *Link;
+  PRIMARY_ROOT_PORT_NODE    *Temp;
+  BOOLEAN                   NodeMatch;
+  EFI_DEVICE_PATH_PROTOCOL  *RootPortPath;
+  EFI_DEVICE_PATH_PROTOCOL  *PciDevicePath;
+
+  if (mPrimaryRootPortList == NULL) {
+    //
+    // no populated PCI primary root ports to parse and match the PCI features
+    // configuration table
+    //
+    *PciFeaturesConfigTable = NULL;
+    return EFI_SUCCESS;
+  }
+
+
+  if (IsDevicePathEnd (PciDevice->DevicePath)){
+    //
+    // the given PCI device does not have a valid device path
+    //
+    *PciFeaturesConfigTable = NULL;
+    return EFI_DEVICE_ERROR;
+  }
+
+
+  Link = &mPrimaryRootPortList->NeighborRootPort;
+  do {
+    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK (Link);
+    RootPortPath = Temp->RootPortDevicePath;
+    PciDevicePath = PciDevice->DevicePath;
+    NodeMatch = FALSE;
+    //
+    // match the device path from the list of primary Root Ports with the given
+    // device; the initial nodes matching in sequence indicate that the given PCI
+    // device belongs to that PCI tree from the root port
+    //
+    if (IsDevicePathEnd (RootPortPath)) {
+      //
+      // critical error as no device path available in root
+      //
+      *PciFeaturesConfigTable = NULL;
+      return EFI_DEVICE_ERROR;
+    }
+
+    if (EfiCompareDevicePath (RootPortPath, PciDevicePath)) {
+      //
+      // the given PCI device is the primary root port itself
+      //
+      *PciFeaturesConfigTable = Temp->OtherPciFeaturesConfigurationTable;
+      return EFI_SUCCESS;
+    }
+    //
+    // check this PCI device belongs to the primary root port of the root bridge
+    // any child PCI device will have the same initial device path nodes  as
+    // its parent root port
+    //
+    while (!IsDevicePathEnd (RootPortPath)){
+
+      if (DevicePathNodeLength (RootPortPath) != DevicePathNodeLength (PciDevicePath)) {
+        //
+        // break to check the next primary root port nodes as does not match
+        //
+        NodeMatch = FALSE;
+        break;
+      }
+      if (CompareMem (RootPortPath, PciDevicePath, DevicePathNodeLength (RootPortPath)) != 0) {
+        //
+        // node does not match, break to check next node
+        //
+        NodeMatch = FALSE;
+        break;
+      }
+      NodeMatch = TRUE;
+      //
+      // advance to next node
+      //
+      RootPortPath = NextDevicePathNode (RootPortPath);
+      PciDevicePath = NextDevicePathNode (PciDevicePath);
+    }
+
+    if (NodeMatch == TRUE) {
+      //
+      // device belongs to primary root port, return its PCI feature configuration
+      // table
+      //
+      *PciFeaturesConfigTable = Temp->OtherPciFeaturesConfigurationTable;
+      return EFI_SUCCESS;
+    }
+
+    //
+    // advance to next Root port node
+    //
+    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;
+}
+
+/**
+  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
+  )
+{
+  if (IsListEmpty (&PciDevice->ChildList)){
+    return TRUE;
+  }
+  return FALSE;
+}
+
+
+/**
+   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;
+  OTHER_PCI_FEATURES_CONFIGURATION_TABLE  *OtherPciFeaturesConfigTable;
+
+  OtherPciFeaturesConfigTable = NULL;
+  Status = GetPciFeaturesConfigurationTable (PciDevice, &OtherPciFeaturesConfigTable);
+  if (EFI_ERROR( Status)) {
+    DEBUG ((
+       DEBUG_WARN, "[Cfg group: 0 {error in dev path}]"
+    ));
+  } else if (OtherPciFeaturesConfigTable == NULL) {
+    DEBUG ((
+        DEBUG_INFO, "[Cfg group: 0]"
+    ));
+  } else {
+    DEBUG ((
+        DEBUG_INFO, "[Cfg group: %d]",
+        OtherPciFeaturesConfigTable->ID
+    ));
+  }
+
+  if (PciConfigPhase == PciFeatureGetDevicePolicy) {
+    Status = GetPciDevicePlatformPolicy (PciDevice);
+    if (EFI_ERROR(Status)) {
+      DEBUG ((
+          DEBUG_ERROR, "Error in obtaining PCI device policy!!!\n"
+      ));
+    }
+  }
+
+  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 (!DeviceExist (Device)) {
+      DEBUG ((
+          DEBUG_ERROR, "::Device [%02x|%02x|%02x] - does not exist!!!\n",
+          Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+      ));
+      continue;
+    }
+    if (IS_PCI_BRIDGE (&Device->Pci)) {
+      DEBUG ((
+          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
+          Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+      ));
+      if (Device->IsPciExp) {
+        Status = 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;
+
+  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 (!DeviceExist (Device)) {
+      DEBUG ((
+          DEBUG_ERROR, "::Device [%02x|%02x|%02x] - does not exist!!!\n",
+          Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+      ));
+      continue;
+    }
+    if (IS_PCI_BRIDGE (&Device->Pci)) {
+      DEBUG ((
+          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
+          Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+      ));
+      if (Device->IsPciExp) {
+        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 and add a node of type PRIMARY_ROOT_PORT_NODE in the list for the primary
+  Root Port so that all its child PCI devices can be identified against the PCI
+  features configuration table group ID, of type OTHER_PCI_FEATURES_CONFIGURATION_TABLE.
+
+  @param BridgePort    A pointer to the PCI_IO_DEVICE
+  @param PortNumber    A UINTN value to identify the PCI feature configuration
+                       table group
+
+  @retval EFI_SUCCESS           success in adding a node of PRIMARY_ROOT_PORT_NODE
+                                to the list
+          EFI_OUT_OF_RESOURCES  unable to get memory for creating the node
+**/
+EFI_STATUS
+AddPrimaryRootPortNode (
+  IN  PCI_IO_DEVICE           *BridgePort,
+  IN  UINTN                   PortNumber
+  )
+{
+  PRIMARY_ROOT_PORT_NODE                  *RootPortNode = NULL;
+  OTHER_PCI_FEATURES_CONFIGURATION_TABLE  *PciConfigTable = NULL;
+
+  RootPortNode = AllocateZeroPool (sizeof (PRIMARY_ROOT_PORT_NODE));
+  if (RootPortNode == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  RootPortNode->Signature                           = PCI_ROOT_PORT_SIGNATURE;
+  RootPortNode->RootPortDevicePath                  = BridgePort->DevicePath;
+  PciConfigTable = AllocateZeroPool (
+                     sizeof (OTHER_PCI_FEATURES_CONFIGURATION_TABLE)
+                    );
+  if (PciConfigTable) {
+    PciConfigTable->ID                          = PortNumber;
+  }
+  RootPortNode->OtherPciFeaturesConfigurationTable  = PciConfigTable;
+
+  if (mPrimaryRootPortList != NULL) {
+    InsertTailList (&mPrimaryRootPortList->NeighborRootPort, &RootPortNode->NeighborRootPort);
+  } else {
+    InitializeListHead (&RootPortNode->NeighborRootPort);
+    mPrimaryRootPortList = RootPortNode;
+  }
+
+  if (PciConfigTable == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  return EFI_SUCCESS;
+}
+
+/**
+  Scan all the nodes of the RootBridge to identify and create a separate list
+  of all primary physical PCI root ports and link each with its own instance of
+  the PCI Feature Configuration Table.
+
+  @param  RootBridge    A pointer to the PCI_IO_DEVICE of the PCI Root Bridge
+
+  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store PCI feature
+                                configuration table for all the physical PCI root
+                                ports given
+          EFI_NOT_FOUND         No PCI Bridge device found
+          EFI_SUCCESS           PCI Feature COnfiguration table created for all
+                                the PCI Rooot ports found
+          EFI_INVALID_PARAMETER invalid parameter passed to the routine which
+                                creates the PCI controller node for the primary
+                                Root post list
+**/
+EFI_STATUS
+RecordPciRootPortBridges (
+  IN  PCI_IO_DEVICE           *RootBridge
+  )
+{
+  EFI_STATUS              Status = EFI_NOT_FOUND;
+  LIST_ENTRY              *Link;
+  PCI_IO_DEVICE           *Device;
+  UINTN                   NumberOfRootPorts;
+
+  DEBUG ((
+      DEBUG_INFO, "<<********** RecordPciRootPortBridges -start *************>>\n"
+  ));
+  NumberOfRootPorts = 0;
+  for ( Link = RootBridge->ChildList.ForwardLink
+      ; Link != &RootBridge->ChildList
+      ; Link = Link->ForwardLink
+  ) {
+    Device = PCI_IO_DEVICE_FROM_LINK (Link);
+    if (!DeviceExist (Device)) {
+      continue;
+    }
+    if (IS_PCI_BRIDGE (&Device->Pci)) {
+      NumberOfRootPorts++;
+      DEBUG ((
+          DEBUG_INFO, "#%d ::Bridge [%02x|%02x|%02x]",
+          NumberOfRootPorts, Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+      ));
+      //
+      // create a primary root port list if that port is connected
+      //
+      if (!IsListEmpty (&Device->ChildList)) {
+        DEBUG ((
+            DEBUG_INFO, "- has downstream device!\n"
+        ));
+        Status = AddPrimaryRootPortNode (Device, NumberOfRootPorts);
+        if (EFI_ERROR (Status)) {
+          DEBUG ((
+              DEBUG_ERROR, "PCI configuration table allocation failure for #%d ::Bridge [%02x|%02x|%02x]\n",
+              NumberOfRootPorts, Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
+          ));
+        }
+      } else {
+        DEBUG ((
+            DEBUG_INFO, "- no downstream device!\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 ();
+    }
+  }
+
+  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
index d06a5e8..b06c140 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
@@ -23,4 +23,150 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #define PCI_FEATURE_SUPPORT_FLAG_CCC  BIT13
 #define PCI_FEATURE_SUPPORT_FLAG_ESYN BIT14
 #define PCI_FEATURE_SUPPORT_FLAG_PTM  BIT20
+
+//
+// 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;
+  //
+  // pointer to PCI_IO_DEVICE of the primary PCI Controller device
+  //
+  EFI_DEVICE_PATH_PROTOCOL                  *RootPortDevicePath;
+  //
+  // pointer to the corresponding PCI feature configuration Table node
+  // all the child PCI devices of the controller are aligned based on this table
+  //
+  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;
+};
+
+
+//
+// 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;
+
+
+/**
+  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
-- 
2.21.0.windows.1


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

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 06/12] PciBusDxe: Integration of setup for PCI feature enumeration
  2019-11-01 15:09 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] New PCI features - MPS, MRRS, RO, NS, CTO Javeed, Ashraf
                   ` (4 preceding siblings ...)
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration Javeed, Ashraf
@ 2019-11-01 15:09 ` Javeed, Ashraf
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] PciBusDxe: Record the PCI-Express Capability Structure Javeed, Ashraf
                   ` (17 subsequent siblings)
  23 siblings, 0 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-01 15:09 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

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

The code changes are made to integrate the setup infrastructure for the
PCI feature enumeration, in the last phase of the PCI Bus driver, after
its registration and its option ROM loading phase is complete.

Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
---
 MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c  | 11 +++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c | 15 ++++++++++++++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h | 11 +++++++++++
 3 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
index 33a0e94..b839102 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
@@ -8,6 +8,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 **/
 
 #include "PciBus.h"
+#include "PciFeatureSupport.h"
 
 //
 // This device structure is serviced as a header.
@@ -170,6 +171,8 @@ DestroyRootBridgeByHandle (
 
     if (Temp->Handle == Controller) {
 
+      DestroyRootBridgePciFeaturesConfigCompletionList (Temp);
+
       RemoveEntryList (CurrentLink);
 
       DestroyPciDeviceTree (Temp);
@@ -818,6 +821,14 @@ StartPciDevicesOnBridge (
   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
     //
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
index ab0e096..9e6671d 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -25,6 +25,19 @@ PRIMARY_ROOT_PORT_NODE                      *mPrimaryRootPortList;
 **/
 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
@@ -699,7 +712,7 @@ ProgramDevicePciFeatures (
   IN PCI_IO_DEVICE          *PciDevice
   )
 {
-  EFI_STATUS           Status;
+  EFI_STATUS           Status = EFI_SUCCESS;
 
   return Status;
 }
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
index b06c140..f92d008 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
@@ -138,6 +138,17 @@ typedef enum {
 }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.
-- 
2.21.0.windows.1


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

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] PciBusDxe: Record the PCI-Express Capability Structure
  2019-11-01 15:09 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] New PCI features - MPS, MRRS, RO, NS, CTO Javeed, Ashraf
                   ` (5 preceding siblings ...)
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 06/12] PciBusDxe: Integration of setup " Javeed, Ashraf
@ 2019-11-01 15:09 ` Javeed, Ashraf
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12] PciBusDxe: New PCI feature Max_Payload_Size Javeed, Ashraf
                   ` (16 subsequent siblings)
  23 siblings, 0 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-01 15:09 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

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

The code changes are made to record the PCI device's PCI-Express
Capability Structure register set during early PCI enumeration phase.
This data shall be used during PCI feature enumeration phase.

Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
---
 MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h               |  6 +++++-
 MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c | 34 ++++++++++++++++++++++------------
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c    | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 78 insertions(+), 13 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index 95a677b..dc29ef3 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -266,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;
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
index c7eafff..2343702 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
index 9e6671d..df9e696 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -467,6 +467,14 @@ GetPciFeaturesConfigurationTable (
     return EFI_SUCCESS;
   }
 
+  //
+  // 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;
+  }
 
   if (IsDevicePathEnd (PciDevice->DevicePath)){
     //
@@ -575,6 +583,45 @@ IsPciRootPortEmpty (
 }
 
 
+/**
+  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.
 
@@ -590,8 +637,12 @@ SetupDevicePciFeatures (
   )
 {
   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)) {
-- 
2.21.0.windows.1


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

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12] PciBusDxe: New PCI feature Max_Payload_Size
  2019-11-01 15:09 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] New PCI features - MPS, MRRS, RO, NS, CTO Javeed, Ashraf
                   ` (6 preceding siblings ...)
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] PciBusDxe: Record the PCI-Express Capability Structure Javeed, Ashraf
@ 2019-11-01 15:09 ` Javeed, Ashraf
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 09/12] PciBusDxe: New PCI feature Max_Read_Req_Size Javeed, Ashraf
                   ` (15 subsequent siblings)
  23 siblings, 0 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-01 15:09 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

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

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

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

This programming of MPS is based on each PCI device's capability, and also
its device-specific platform policy obtained using the new PCI Platform
Protocol interface, 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.h             |   4 ++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h  |   5 +++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c |  59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h |  32 ++++++++++++++++++++++++++++++++
 5 files changed, 257 insertions(+)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index dc29ef3..065ae54 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -286,6 +286,10 @@ struct _PCI_IO_DEVICE {
   // This field is used to support this case.
   //
   UINT16                                    BridgeIoAlignment;
+  //
+  // Other PCI features setup flags
+  //
+  UINT8                                     SetupMPS;
 };
 
 #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
index df9e696..8fdaa05 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -582,6 +582,146 @@ IsPciRootPortEmpty (
   return FALSE;
 }
 
+/**
+  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;
+        }
+      }
+    } 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) {
+      PciFeaturesConfigurationTable->Max_Payload_Size = MpsValue;
+    }
+  }
+
+  DEBUG (( DEBUG_INFO,
+      "MPS: %d [DevCap:%d],",
+      PciDevice->SetupMPS, PciDeviceCap.Bits.MaxPayloadSize
+  ));
+  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;
+  EFI_TPL                     OldTpl;
+
+  PcieDev.Uint16 = 0;
+  Offset = PciDevice->PciExpressCapabilityOffset +
+               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint16,
+                                  Offset,
+                                  1,
+                                  &PcieDev.Uint16
+                                );
+  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, "MPS=%d,", PciDevice->SetupMPS));
+
+    //
+    // Raise TPL to high level to disable timer interrupt while the write operation completes
+    //
+    OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+    Status = PciDevice->PciIo.Pci.Write (
+                                    &PciDevice->PciIo,
+                                    EfiPciIoWidthUint16,
+                                    Offset,
+                                    1,
+                                    &PcieDev.Uint16
+                                  );
+    //
+    // Restore TPL to its original level
+    //
+    gBS->RestoreTPL (OldTpl);
+
+    if (!EFI_ERROR(Status)) {
+      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
+    } else {
+      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) write error!",
+          Offset
+      ));
+    }
+  } else {
+    DEBUG (( DEBUG_INFO, "No write of MPS=%d,", PciDevice->SetupMPS));
+  }
+
+  return Status;
+}
 
 /**
   helper routine to dump the PCIe Device Port Type
@@ -669,6 +809,18 @@ SetupDevicePciFeatures (
     }
   }
 
+  DEBUG ((DEBUG_INFO, "["));
+  //
+  // process the PCI device Max_Payload_Size feature
+  //
+  if (SetupMaxPayloadSize ()) {
+    Status = ProcessMaxPayloadSize (
+              PciDevice,
+              PciConfigPhase,
+              OtherPciFeaturesConfigTable
+              );
+  }
+  DEBUG ((DEBUG_INFO, "]\n"));
   return Status;
 }
 
@@ -765,6 +917,10 @@ ProgramDevicePciFeatures (
 {
   EFI_STATUS           Status = EFI_SUCCESS;
 
+  if (SetupMaxPayloadSize ()) {
+    Status = OverrideMaxPayloadSize (PciDevice);
+  }
+  DEBUG (( DEBUG_INFO, "\n"));
   return Status;
 }
 
@@ -878,6 +1034,7 @@ AddPrimaryRootPortNode (
                     );
   if (PciConfigTable) {
     PciConfigTable->ID                          = PortNumber;
+    PciConfigTable->Max_Payload_Size            = PCIE_MAX_PAYLOAD_SIZE_4096B;
   }
   RootPortNode->OtherPciFeaturesConfigurationTable  = PciConfigTable;
 
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
index f92d008..e5ac2a3 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
@@ -79,6 +79,11 @@ 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;
 };
 
 
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
index 238959e..99badd6 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
@@ -356,6 +356,63 @@ GetPlatformPciOptionRom (
   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;
+  }
+}
+
+/**
+  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;
+  }
+}
+
 /**
   Generic routine to setup the PCI features as per its predetermined defaults.
 **/
@@ -364,6 +421,7 @@ SetupDefaultsDevicePlatformPolicy (
   IN  PCI_IO_DEVICE               *PciDevice
   )
 {
+  PciDevice->SetupMPS = EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO;
 }
 
 /**
@@ -399,6 +457,7 @@ GetPciDevicePlatformPolicyEx (
       //
       // platform chipset policies are returned for this PCI device
       //
+      PciIoDevice->SetupMPS = PciPlatformExtendedPolicy.DeviceCtlMPS;
 
       DEBUG ((
           DEBUG_INFO, "[device policy: platform]"
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
index a13131c..786c00d 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
@@ -124,4 +124,36 @@ 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
+);
+
+/**
+  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
+);
 #endif
-- 
2.21.0.windows.1


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

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 09/12] PciBusDxe: New PCI feature Max_Read_Req_Size
  2019-11-01 15:09 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] New PCI features - MPS, MRRS, RO, NS, CTO Javeed, Ashraf
                   ` (7 preceding siblings ...)
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12] PciBusDxe: New PCI feature Max_Payload_Size Javeed, Ashraf
@ 2019-11-01 15:09 ` Javeed, Ashraf
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 10/12] PciBusDxe: New PCI feature Relax Ordering Javeed, Ashraf
                   ` (14 subsequent siblings)
  23 siblings, 0 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-01 15:09 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

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

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

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

This programming of MRRS gets the device-specific platform policy using
the new PCI Platform Protocol interface, 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.h             |   1 +
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h  |   9 +++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c |  59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h |  32 ++++++++++++++++++++++++++++++++
 5 files changed, 305 insertions(+)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index 065ae54..38abd20 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -290,6 +290,7 @@ struct _PCI_IO_DEVICE {
   // 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/PciFeatureSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
index 8fdaa05..614285f 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -650,6 +650,121 @@ ProcessMaxPayloadSize (
   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, "MRRS: %d,", PciDevice->SetupMRRS));
+
+  return EFI_SUCCESS;
+}
+
 /**
   Overrides the PCI Device Control register MaxPayloadSize register field; if
   the hardware value is different than the intended value.
@@ -723,6 +838,79 @@ OverrideMaxPayloadSize (
   return Status;
 }
 
+/**
+  Overrides the PCI Device Control register Max_Read_Req_Size register field; if
+  the hardware value is different than the intended value.
+
+  @param  PciDevice             A pointer to the PCI_IO_DEVICE instance.
+
+  @retval EFI_SUCCESS           The data was read from or written to the PCI controller.
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
+                                valid for the PCI configuration header of the PCI controller.
+  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
+
+**/
+EFI_STATUS
+OverrideMaxReadReqSize (
+  IN PCI_IO_DEVICE          *PciDevice
+  )
+{
+  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
+  UINT32                      Offset;
+  EFI_STATUS                  Status;
+  EFI_TPL                     OldTpl;
+
+  PcieDev.Uint16 = 0;
+  Offset = PciDevice->PciExpressCapabilityOffset +
+               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint16,
+                                  Offset,
+                                  1,
+                                  &PcieDev.Uint16
+                                );
+  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,", PciDevice->SetupMRRS));
+
+    //
+    // Raise TPL to high level to disable timer interrupt while the write operation completes
+    //
+    OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+    Status = PciDevice->PciIo.Pci.Write (
+                                    &PciDevice->PciIo,
+                                    EfiPciIoWidthUint16,
+                                    Offset,
+                                    1,
+                                    &PcieDev.Uint16
+                                  );
+    //
+    // Restore TPL to its original level
+    //
+    gBS->RestoreTPL (OldTpl);
+
+    if (!EFI_ERROR(Status)) {
+      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
+    } else {
+      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) write error!",
+          Offset
+      ));
+    }
+  } else {
+    DEBUG (( DEBUG_INFO, "No write of MRRS=%d,", PciDevice->SetupMRRS));
+  }
+
+  return Status;
+}
+
 /**
   helper routine to dump the PCIe Device Port Type
 **/
@@ -820,6 +1008,17 @@ SetupDevicePciFeatures (
               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
+              );
+  }
   DEBUG ((DEBUG_INFO, "]\n"));
   return Status;
 }
@@ -920,6 +1119,9 @@ ProgramDevicePciFeatures (
   if (SetupMaxPayloadSize ()) {
     Status = OverrideMaxPayloadSize (PciDevice);
   }
+  if (SetupMaxReadReqSize ()) {
+    Status = OverrideMaxReadReqSize (PciDevice);
+  }
   DEBUG (( DEBUG_INFO, "\n"));
   return Status;
 }
@@ -1035,6 +1237,8 @@ AddPrimaryRootPortNode (
   if (PciConfigTable) {
     PciConfigTable->ID                          = PortNumber;
     PciConfigTable->Max_Payload_Size            = PCIE_MAX_PAYLOAD_SIZE_4096B;
+    PciConfigTable->Max_Read_Request_Size       = PCIE_MAX_READ_REQ_SIZE_4096B;
+    PciConfigTable->Lock_Max_Read_Request_Size  = FALSE;
   }
   RootPortNode->OtherPciFeaturesConfigurationTable  = PciConfigTable;
 
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
index e5ac2a3..96ee6ff 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
@@ -84,6 +84,15 @@ struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE {
   // size among all the PCI devices in the PCI hierarchy
   //
   UINT8                                     Max_Payload_Size;
+  //
+  // to configure the PCI feature maximum read request size to maintain the memory
+  // requester size among all the PCI devices in the PCI hierarchy
+  //
+  UINT8                                     Max_Read_Request_Size;
+  //
+  // lock the Max_Read_Request_Size for the entire PCI tree of a root port
+  //
+  BOOLEAN                                   Lock_Max_Read_Request_Size;
 };
 
 
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
index 99badd6..f032b5d 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
@@ -379,6 +379,29 @@ SetupMpsAsPerDeviceCapability (
   }
 }
 
+/**
+  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
@@ -413,6 +436,40 @@ TranslateMpsSetupValueToPci (
   }
 }
 
+/**
+  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.
 **/
@@ -422,6 +479,7 @@ SetupDefaultsDevicePlatformPolicy (
   )
 {
   PciDevice->SetupMPS = EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO;
+  PciDevice->SetupMRRS = EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO;
 }
 
 /**
@@ -458,6 +516,7 @@ GetPciDevicePlatformPolicyEx (
       // platform chipset policies are returned for this PCI device
       //
       PciIoDevice->SetupMPS = PciPlatformExtendedPolicy.DeviceCtlMPS;
+      PciIoDevice->SetupMRRS = PciPlatformExtendedPolicy.DeviceCtlMRRS;
 
       DEBUG ((
           DEBUG_INFO, "[device policy: platform]"
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
index 786c00d..8ed3836 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
@@ -141,6 +141,22 @@ 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
@@ -156,4 +172,20 @@ 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
-- 
2.21.0.windows.1


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

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 10/12] PciBusDxe: New PCI feature Relax Ordering
  2019-11-01 15:09 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] New PCI features - MPS, MRRS, RO, NS, CTO Javeed, Ashraf
                   ` (8 preceding siblings ...)
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 09/12] PciBusDxe: New PCI feature Max_Read_Req_Size Javeed, Ashraf
@ 2019-11-01 15:09 ` Javeed, Ashraf
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 11/12] PciBusDxe: New PCI feature No-Snoop Javeed, Ashraf
                   ` (13 subsequent siblings)
  23 siblings, 0 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-01 15:09 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

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

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

The code changes are made to configure only those PCI devices which are
requested to override by platform through the new PCI Platform protocol
interface for device-specific policies.

Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
---
 MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h             |  2 ++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h  | 26 ++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 150 insertions(+)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index 38abd20..9f017b7 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -82,6 +82,7 @@ typedef enum {
 #include "PciHotPlugSupport.h"
 #include "PciLib.h"
 #include "PciPlatformSupport.h"
+#include "PciFeatureSupport.h"
 
 #define VGABASE1  0x3B0
 #define VGALIMIT1 0x3BB
@@ -291,6 +292,7 @@ struct _PCI_IO_DEVICE {
   //
   UINT8                                     SetupMPS;
   UINT8                                     SetupMRRS;
+  PCI_FEATURE_POLICY                        SetupRO;
 };
 
 #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
index 614285f..a60cb42 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -911,6 +911,81 @@ OverrideMaxReadReqSize (
   return Status;
 }
 
+/**
+  Overrides the PCI Device Control register Relax Order register field; if
+  the hardware value is different than the intended value.
+
+  @param  PciDevice             A pointer to the PCI_IO_DEVICE instance.
+
+  @retval EFI_SUCCESS           The data was read from or written to the PCI device.
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
+                                valid for the PCI configuration header of the PCI controller.
+  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
+
+**/
+EFI_STATUS
+OverrideRelaxOrder (
+  IN PCI_IO_DEVICE          *PciDevice
+  )
+{
+  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
+  UINT32                      Offset;
+  EFI_STATUS                  Status;
+  EFI_TPL                     OldTpl;
+
+  PcieDev.Uint16 = 0;
+  Offset = PciDevice->PciExpressCapabilityOffset +
+               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint16,
+                                  Offset,
+                                  1,
+                                  &PcieDev.Uint16
+                                );
+  if (EFI_ERROR(Status)){
+    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) read error!",
+        Offset
+    ));
+    return Status;
+  }
+  if (PciDevice->SetupRO.Override
+      &&  PcieDev.Bits.RelaxedOrdering != PciDevice->SetupRO.Act
+      ) {
+    PcieDev.Bits.RelaxedOrdering = PciDevice->SetupRO.Act;
+    DEBUG (( DEBUG_INFO, "RO=%d,", PciDevice->SetupRO.Act));
+
+    //
+    // Raise TPL to high level to disable timer interrupt while the write operation completes
+    //
+    OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+    Status = PciDevice->PciIo.Pci.Write (
+                                    &PciDevice->PciIo,
+                                    EfiPciIoWidthUint16,
+                                    Offset,
+                                    1,
+                                    &PcieDev.Uint16
+                                  );
+    //
+    // Restore TPL to its original level
+    //
+    gBS->RestoreTPL (OldTpl);
+
+    if (!EFI_ERROR(Status)) {
+      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
+    } else {
+      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) write error!",
+          Offset
+      ));
+    }
+  } else {
+    DEBUG (( DEBUG_INFO, "No write of RO,", PciDevice->SetupRO.Act));
+  }
+
+  return Status;
+}
+
 /**
   helper routine to dump the PCIe Device Port Type
 **/
@@ -1122,6 +1197,9 @@ ProgramDevicePciFeatures (
   if (SetupMaxReadReqSize ()) {
     Status = OverrideMaxReadReqSize (PciDevice);
   }
+  if (SetupRelaxOrder ()) {
+    Status = OverrideRelaxOrder (PciDevice);
+  }
   DEBUG (( DEBUG_INFO, "\n"));
   return Status;
 }
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
index 96ee6ff..5044dc2 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
@@ -40,6 +40,11 @@ typedef struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE  OTHER_PCI_FEATURES_CONFI
 //
 typedef struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST  PCI_FEATURE_CONFIGURATION_COMPLETION_LIST;
 
+//
+// define the data type for the PCI feature policy support
+//
+typedef struct _PCI_FEATURE_POLICY  PCI_FEATURE_POLICY;
+
 //
 // Signature value for the PCI Root Port node
 //
@@ -151,6 +156,27 @@ typedef enum {
 
 }PCI_FEATURE_CONFIGURATION_PHASE;
 
+//
+// declaration for the data type to harbor the PCI feature policies
+//
+struct  _PCI_FEATURE_POLICY {
+  //
+  // if set, it indicates the feature should be enabled
+  // if clear, it indicates the feature should be disabled
+  //
+  UINT8   Act : 1;
+  //
+  // this field will be specific to feature, it can be implementation specific
+  // or it can be reserved and remain unused
+  //
+  UINT8   Support : 6;
+  //
+  // if set indicates override the feature policy defined by the members above
+  // if clear it indicates that this feature policy should be ignored completely
+  // this means the above two members should not be used
+  //
+  UINT8   Override : 1;
+};
 
 /**
   Main routine to indicate platform selection of any of the other PCI features
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
index f032b5d..f1e7039 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
@@ -470,6 +470,45 @@ TranslateMrrsSetupValueToPci (
   }
 }
 
+/**
+  Routine to set the device-specific policy for the PCI feature Relax Ordering
+
+  @param  RelaxOrder    value corresponding to data type EFI_PCI_CONF_RELAX_ORDER
+  @param  PciDevice     A pointer to PCI_IO_DEVICE
+**/
+VOID
+SetDevicePolicyRelaxOrder (
+  IN  EFI_PCI_CONF_RELAX_ORDER    RelaxOrder,
+  OUT PCI_IO_DEVICE               *PciDevice
+  )
+{
+  //
+  // implementation specific rules for the usage of PCI_FEATURE_POLICY members
+  // exclusively for the PCI Feature Relax Ordering (RO)
+  //
+  // .Override = 0 to skip this PCI feature RO for the PCI device
+  // .Override = 1 to program this RO PCI feature
+  //      .Act = 1 to enable the RO in the PCI device
+  //      .Act = 0 to disable the RO in the PCI device
+  //
+  switch (RelaxOrder) {
+    case  EFI_PCI_CONF_RO_AUTO:
+      PciDevice->SetupRO.Override = 0;
+      break;
+    case  EFI_PCI_CONF_RO_DISABLE:
+      PciDevice->SetupRO.Override = 1;
+      PciDevice->SetupRO.Act = 0;
+      break;
+    case  EFI_PCI_CONF_RO_ENABLE:
+      PciDevice->SetupRO.Override = 1;
+      PciDevice->SetupRO.Act = 1;
+      break;
+    default:
+      PciDevice->SetupRO.Override = 0;
+      break;
+  }
+}
+
 /**
   Generic routine to setup the PCI features as per its predetermined defaults.
 **/
@@ -480,6 +519,7 @@ SetupDefaultsDevicePlatformPolicy (
 {
   PciDevice->SetupMPS = EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO;
   PciDevice->SetupMRRS = EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO;
+  PciDevice->SetupRO.Override = 0;
 }
 
 /**
@@ -517,6 +557,10 @@ GetPciDevicePlatformPolicyEx (
       //
       PciIoDevice->SetupMPS = PciPlatformExtendedPolicy.DeviceCtlMPS;
       PciIoDevice->SetupMRRS = PciPlatformExtendedPolicy.DeviceCtlMRRS;
+      //
+      // set device specific policy for Relax Ordering
+      //
+      SetDevicePolicyRelaxOrder (PciPlatformExtendedPolicy.DeviceCtlRelaxOrder, PciIoDevice);
 
       DEBUG ((
           DEBUG_INFO, "[device policy: platform]"
-- 
2.21.0.windows.1


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

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 11/12] PciBusDxe: New PCI feature No-Snoop
  2019-11-01 15:09 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] New PCI features - MPS, MRRS, RO, NS, CTO Javeed, Ashraf
                   ` (9 preceding siblings ...)
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 10/12] PciBusDxe: New PCI feature Relax Ordering Javeed, Ashraf
@ 2019-11-01 15:09 ` Javeed, Ashraf
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 12/12] PciBusDxe: New PCI feature Completion Timeout Javeed, Ashraf
                   ` (12 subsequent siblings)
  23 siblings, 0 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-01 15:09 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

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

The code changes are made; as per the PCI Base Specification 4 Revision
1; to enable the configuration of new PCI feature No-Snoop (NS), which
enables the PCI function to initiate requests if it does not require har-
dware enforced cache-coherency for its transactions.

The code changes are made to configure only those PCI devices which are
requested to override by platform through the new PCI Platform protocol
interface for device-specific policies.

Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
---
 MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h             |  1 +
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 124 insertions(+)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index 9f017b7..be1c341 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -293,6 +293,7 @@ struct _PCI_IO_DEVICE {
   UINT8                                     SetupMPS;
   UINT8                                     SetupMRRS;
   PCI_FEATURE_POLICY                        SetupRO;
+  PCI_FEATURE_POLICY                        SetupNS;
 };
 
 #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
index a60cb42..a7f0a2f 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -986,6 +986,81 @@ OverrideRelaxOrder (
   return Status;
 }
 
+/**
+  Overrides the PCI Device Control register No-Snoop register field; if
+  the hardware value is different than the intended value.
+
+  @param  PciDevice             A pointer to the PCI_IO_DEVICE instance.
+
+  @retval EFI_SUCCESS           The data was read from or written to the PCI device.
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
+                                valid for the PCI configuration header of the PCI controller.
+  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
+
+**/
+EFI_STATUS
+OverrideNoSnoop (
+  IN PCI_IO_DEVICE          *PciDevice
+  )
+{
+  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
+  UINT32                      Offset;
+  EFI_STATUS                  Status;
+  EFI_TPL                     OldTpl;
+
+  PcieDev.Uint16 = 0;
+  Offset = PciDevice->PciExpressCapabilityOffset +
+               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
+  Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint16,
+                                  Offset,
+                                  1,
+                                  &PcieDev.Uint16
+                                );
+  if (EFI_ERROR(Status)){
+    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) read error!",
+        Offset
+    ));
+    return Status;
+  }
+  if (PciDevice->SetupRO.Override
+      &&  PcieDev.Bits.NoSnoop != PciDevice->SetupNS.Act
+      ) {
+    PcieDev.Bits.NoSnoop = PciDevice->SetupNS.Act;
+    DEBUG (( DEBUG_INFO, "NS=%d", PciDevice->SetupNS.Act));
+
+    //
+    // Raise TPL to high level to disable timer interrupt while the write operation completes
+    //
+    OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+    Status = PciDevice->PciIo.Pci.Write (
+                                    &PciDevice->PciIo,
+                                    EfiPciIoWidthUint16,
+                                    Offset,
+                                    1,
+                                    &PcieDev.Uint16
+                                  );
+    //
+    // Restore TPL to its original level
+    //
+    gBS->RestoreTPL (OldTpl);
+
+    if (!EFI_ERROR(Status)) {
+      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
+    } else {
+      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) write error!",
+          Offset
+      ));
+    }
+  } else {
+    DEBUG (( DEBUG_INFO, "No write of NS,", PciDevice->SetupRO.Act));
+  }
+
+  return Status;
+}
+
 /**
   helper routine to dump the PCIe Device Port Type
 **/
@@ -1200,6 +1275,9 @@ ProgramDevicePciFeatures (
   if (SetupRelaxOrder ()) {
     Status = OverrideRelaxOrder (PciDevice);
   }
+  if (SetupNoSnoop ()) {
+    Status = OverrideNoSnoop (PciDevice);
+  }
   DEBUG (( DEBUG_INFO, "\n"));
   return Status;
 }
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
index f1e7039..47295cd 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
@@ -509,6 +509,46 @@ SetDevicePolicyRelaxOrder (
   }
 }
 
+/**
+  Routine to set the device-specific policy for the PCI feature No-Snoop enable
+  or disable
+
+  @param  NoSnoop       value corresponding to data type EFI_PCI_CONF_NO_SNOOP
+  @param  PciDevice     A pointer to PCI_IO_DEVICE
+**/
+VOID
+SetDevicePolicyNoSnoop (
+  IN  EFI_PCI_CONF_NO_SNOOP       NoSnoop,
+  OUT PCI_IO_DEVICE               *PciDevice
+  )
+{
+  //
+  // implementation specific rules for the usage of PCI_FEATURE_POLICY members
+  // exclusively for the PCI Feature No-Snoop
+  //
+  // .Override = 0 to skip this PCI feature No-Snoop for the PCI device
+  // .Override = 1 to program this No-Snoop PCI feature
+  //      .Act = 1 to enable the No-Snoop in the PCI device
+  //      .Act = 0 to disable the No-Snoop in the PCI device
+  //
+  switch (NoSnoop) {
+    case  EFI_PCI_CONF_NS_AUTO:
+      PciDevice->SetupNS.Override = 0;
+      break;
+    case  EFI_PCI_CONF_NS_DISABLE:
+      PciDevice->SetupNS.Override = 1;
+      PciDevice->SetupNS.Act = 0;
+      break;
+    case  EFI_PCI_CONF_NS_ENABLE:
+      PciDevice->SetupNS.Override = 1;
+      PciDevice->SetupNS.Act = 1;
+      break;
+    default:
+      PciDevice->SetupNS.Override = 0;
+      break;
+  }
+}
+
 /**
   Generic routine to setup the PCI features as per its predetermined defaults.
 **/
@@ -520,6 +560,7 @@ SetupDefaultsDevicePlatformPolicy (
   PciDevice->SetupMPS = EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO;
   PciDevice->SetupMRRS = EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO;
   PciDevice->SetupRO.Override = 0;
+  PciDevice->SetupNS.Override = 0;
 }
 
 /**
@@ -561,6 +602,10 @@ GetPciDevicePlatformPolicyEx (
       // set device specific policy for Relax Ordering
       //
       SetDevicePolicyRelaxOrder (PciPlatformExtendedPolicy.DeviceCtlRelaxOrder, PciIoDevice);
+      //
+      // set the device specific policy for No-Snoop
+      //
+      SetDevicePolicyNoSnoop (PciPlatformExtendedPolicy.DeviceCtlNoSnoop, PciIoDevice);
 
       DEBUG ((
           DEBUG_INFO, "[device policy: platform]"
-- 
2.21.0.windows.1


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

* [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 12/12] PciBusDxe: New PCI feature Completion Timeout
  2019-11-01 15:09 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] New PCI features - MPS, MRRS, RO, NS, CTO Javeed, Ashraf
                   ` (10 preceding siblings ...)
  2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 11/12] PciBusDxe: New PCI feature No-Snoop Javeed, Ashraf
@ 2019-11-01 15:09 ` Javeed, Ashraf
       [not found] ` <15D3127A726D26A6.7420@groups.io>
                   ` (11 subsequent siblings)
  23 siblings, 0 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-01 15:09 UTC (permalink / raw)
  To: devel; +Cc: Jian J Wang, Hao A Wu, Ray Ni

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

The code changes are made; as per the PCI Base Specification 4 Revision
1; to enable the configuration of new PCI feature Completion Timeout
(CTO), which enables the PCI function to wait on programmed duration for
its transactions before timeout, or disable its detection mechanism.

The code changes are made to configure only those PCI devices which are
requested to override by platform through the new PCI Platform protocol
interface for device-specific policies. The changes are made to also com-
ply with the device-specific capability attributes.

The code follows the below implementation specific rules in case the req-
uested platform policy does not match with the device-specific capability
attributes:-
(1) if device is capable of Range A only and if platform ask for any of
    ranges B, C, D; than this implementation will only program the default
    range value for the duration of 50us to 50ms
(2) if device is capable of Range B, or range B & C, or Ranges B, C & D
    only and if the platform ask for the Range A; than this implementation
    will only program the default range value for the duration of 50us to
    50ms
(3) if the device is capable of Range B only, or the ranges A & B; and if
    the platform ask for Range C, or Range D values, than this implement-
    ation will only program the Range B value for the duration of 65ms to
    210ms
(4) if the device is capable of Ranges B & C, or Ranges A, B, and C; and
    if the platform ask for Range D values; than this implementation will
    only program the Range C for the duration of 1s to 3.5s


Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
---
 MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h             |   1 +
 MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  | 413 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c |  84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 498 insertions(+)

diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index be1c341..b6ec14f 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -294,6 +294,7 @@ struct _PCI_IO_DEVICE {
   UINT8                                     SetupMRRS;
   PCI_FEATURE_POLICY                        SetupRO;
   PCI_FEATURE_POLICY                        SetupNS;
+  PCI_FEATURE_POLICY                        SetupCTO;
 };
 
 #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
index a7f0a2f..ba0de0d 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
@@ -765,6 +765,294 @@ ProcessMaxReadReqSize (
   return EFI_SUCCESS;
 }
 
+/**
+  To determine the CTO Range A values
+
+  @param  CtoValue    input CTO range value from 0 to 14
+  @retval TRUE        the given CTO value belongs to Range A
+          FALSE       the given value does not belong to Range A
+**/
+BOOLEAN
+IsCtoRangeA (
+  IN  UINT8   CtoValue
+  )
+{
+  switch (CtoValue) {
+    case  PCIE_COMPLETION_TIMEOUT_50US_100US:
+    case  PCIE_COMPLETION_TIMEOUT_1MS_10MS:
+      return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+  To determine the CTO Range B values
+
+  @param  CtoValue    input CTO range value from 0 to 14
+  @retval TRUE        the given CTO value belongs to Range B
+          FALSE       the given value does not belong to Range B
+**/
+BOOLEAN
+IsCtoRangeB (
+  IN  UINT8   CtoValue
+  )
+{
+  switch (CtoValue) {
+    case  PCIE_COMPLETION_TIMEOUT_16MS_55MS:
+    case  PCIE_COMPLETION_TIMEOUT_65MS_210MS:
+      return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+  To determine the CTO Range C values
+
+  @param  CtoValue    input CTO range value from 0 to 14
+  @retval TRUE        the given CTO value belongs to Range C
+          FALSE       the given value does not belong to Range C
+**/
+BOOLEAN
+IsCtoRangeC (
+  IN  UINT8   CtoValue
+  )
+{
+  switch (CtoValue) {
+    case  PCIE_COMPLETION_TIMEOUT_260MS_900MS:
+    case  PCIE_COMPLETION_TIMEOUT_1S_3_5S:
+      return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+  To determine the CTO Range D values
+
+  @param  CtoValue    input CTO range value from 0 to 14
+  @retval TRUE        the given CTO value belongs to Range D
+          FALSE       the given value does not belong to Range D
+**/
+BOOLEAN
+IsCtoRangeD (
+  IN  UINT8   CtoValue
+  )
+{
+  switch (CtoValue) {
+    case  PCIE_COMPLETION_TIMEOUT_4S_13S:
+    case  PCIE_COMPLETION_TIMEOUT_17S_64S:
+      return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+  The main routine which process the PCI feature Completion Timeout as per the
+  device-specific platform policy, as well as in complaince with the PCI Base
+  specification Revision 4.
+
+  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
+  @param PciConfigPhase                 for the PCI feature configuration phases:
+                                        PciFeatureGetDevicePolicy & PciFeatureSetupPhase
+
+  @retval EFI_SUCCESS                   processing of PCI feature CTO is successful.
+**/
+EFI_STATUS
+ProcessCompletionTimeout (
+  IN  PCI_IO_DEVICE                           *PciDevice,
+  IN  PCI_FEATURE_CONFIGURATION_PHASE         PciConfigPhase
+  )
+{
+  PCI_REG_PCIE_DEVICE_CAPABILITY2 DeviceCap2;
+  UINT8                           CtoRangeValue;
+
+  if (PciConfigPhase != PciFeatureGetDevicePolicy) {
+    //
+    // no reprocessing required for device CTO configuration
+    //
+    return  EFI_SUCCESS;
+  }
+
+  if (!PciDevice->SetupCTO.Override) {
+    //
+    // No override of CTO is required for this device
+    //
+    return  EFI_SUCCESS;
+  }
+
+  //
+  // determine the CTO range values as per its device capability register
+  //
+  DeviceCap2.Uint32 = PciDevice->PciExpStruct.DeviceCapability2.Uint32;
+  if (!DeviceCap2.Bits.CompletionTimeoutRanges
+      && !DeviceCap2.Bits.CompletionTimeoutDisable
+  ) {
+    //
+    // device does not support the CTO mechanism, hence no override is applicable
+    //
+    return EFI_SUCCESS;
+  }
+
+  //
+  // override the device CTO values if applicable
+  //
+  if (PciDevice->SetupCTO.Act) {
+    //
+    // program the CTO range values
+    //
+    if (DeviceCap2.Bits.CompletionTimeoutRanges) {
+      CtoRangeValue = PCIE_COMPLETION_TIMEOUT_50US_50MS;
+      //
+      // in case if the supported CTO range and the requirement from platform
+      // policy does not match, than the CTO range setting would be based on
+      // this driver's implementation specific, and its rules are as follows:-
+      //
+      // if device is capable of Range A only and if platform ask for any of
+      // ranges B, C, D; than this implementation will only program the default
+      // range value for the duration of 50us to 50ms.
+      //
+      // if device is capable of Range B, or range B & C, or Ranges B, C & D only
+      // and if the platform ask for the Range A; than this implementation will
+      // only program the default range value for the duration of 50us to 50ms.
+      //
+      // if the device is capable of Range B only, or the ranges A & B; and the
+      // platform ask for Range C, or Range D values, than this implementation
+      // will only program the Range B value for the duration of 65ms to 210ms.
+      //
+      // if the device is capable of Ranges B & C, or Ranges A, B, and C; and
+      // if the platform ask for Range D values; than this implementation will
+      // only program the Range C for the duration of 1s to 3.5s.
+      //
+
+      switch (DeviceCap2.Bits.CompletionTimeoutRanges) {
+        case  PCIE_COMPLETION_TIMEOUT_RANGE_A_SUPPORTED:
+          if (IsCtoRangeA (PciDevice->SetupCTO.Support)) {
+            CtoRangeValue = PciDevice->SetupCTO.Support;
+          }
+          //
+          // if device is capable of Range A only and if platform ask for any of
+          // ranges B, C, D; than this implementation will only program the default
+          // range value for the duration of 50us to 50ms.
+          //
+          if (IsCtoRangeB (PciDevice->SetupCTO.Support)
+              || IsCtoRangeC (PciDevice->SetupCTO.Support)
+              || IsCtoRangeD (PciDevice->SetupCTO.Support)
+          ) {
+            CtoRangeValue = PCIE_COMPLETION_TIMEOUT_50US_50MS;
+          }
+          break;
+
+        case  PCIE_COMPLETION_TIMEOUT_RANGE_B_SUPPORTED:
+          //
+          // if device is capable of Range B, or range B & C, or Ranges B, C & D only
+          // and if the platform ask for the Range A; than this implementation will
+          // only program the default range value for the duration of 50us to 50ms.
+          //
+          if (IsCtoRangeA (PciDevice->SetupCTO.Support)) {
+            CtoRangeValue = PCIE_COMPLETION_TIMEOUT_50US_50MS;
+          }
+
+          if (IsCtoRangeB (PciDevice->SetupCTO.Support)) {
+            CtoRangeValue = PciDevice->SetupCTO.Support;
+          }
+          //
+          // if the device is capable of Range B only, or the ranges A & B; and the
+          // platform ask for Range C, or Range D values, than this implementation
+          // will only program the Range B value for the duration of 65ms to 210ms.
+          //
+          if (IsCtoRangeC (PciDevice->SetupCTO.Support)
+              || IsCtoRangeD (PciDevice->SetupCTO.Support)
+          ) {
+            CtoRangeValue = PCIE_COMPLETION_TIMEOUT_65MS_210MS;
+          }
+          break;
+
+        case  PCIE_COMPLETION_TIMEOUT_RANGE_B_C_SUPPORTED:
+          if (IsCtoRangeA (PciDevice->SetupCTO.Support)) {
+            CtoRangeValue = PCIE_COMPLETION_TIMEOUT_50US_50MS;
+          }
+
+          if (IsCtoRangeB (PciDevice->SetupCTO.Support)
+              || IsCtoRangeC (PciDevice->SetupCTO.Support)
+              ) {
+            CtoRangeValue = PciDevice->SetupCTO.Support;
+          }
+          //
+          // if the device is capable of Ranges B & C, or Ranges A, B, and C; and
+          // if the platform ask for Range D values; than this implementation will
+          // only program the Range C for the duration of 1s to 3.5s.
+          //
+          if (IsCtoRangeD (PciDevice->SetupCTO.Support)) {
+            CtoRangeValue = PCIE_COMPLETION_TIMEOUT_1S_3_5S;
+          }
+          break;
+
+        case  PCIE_COMPLETION_TIMEOUT_RANGE_B_C_D_SUPPORTED:
+          if (IsCtoRangeA (PciDevice->SetupCTO.Support)) {
+            CtoRangeValue = PCIE_COMPLETION_TIMEOUT_50US_50MS;
+          }
+          if (IsCtoRangeB (PciDevice->SetupCTO.Support)
+              || IsCtoRangeC (PciDevice->SetupCTO.Support)
+              || IsCtoRangeD (PciDevice->SetupCTO.Support)
+          ) {
+            CtoRangeValue = PciDevice->SetupCTO.Support;
+          }
+          break;
+
+        case  PCIE_COMPLETION_TIMEOUT_RANGE_A_B_SUPPORTED:
+          if (IsCtoRangeA (PciDevice->SetupCTO.Support)
+              || IsCtoRangeB (PciDevice->SetupCTO.Support)
+              ) {
+            CtoRangeValue = PciDevice->SetupCTO.Support;
+          }
+          if (IsCtoRangeC (PciDevice->SetupCTO.Support)
+              || IsCtoRangeD (PciDevice->SetupCTO.Support)
+          ) {
+            CtoRangeValue = PCIE_COMPLETION_TIMEOUT_65MS_210MS;
+          }
+          break;
+
+        case  PCIE_COMPLETION_TIMEOUT_RANGE_A_B_C_SUPPORTED:
+          if (IsCtoRangeA (PciDevice->SetupCTO.Support)
+              || IsCtoRangeB (PciDevice->SetupCTO.Support)
+              || IsCtoRangeC (PciDevice->SetupCTO.Support)
+          ) {
+            CtoRangeValue = PciDevice->SetupCTO.Support;
+          }
+          if (IsCtoRangeD (PciDevice->SetupCTO.Support)) {
+            CtoRangeValue = PCIE_COMPLETION_TIMEOUT_1S_3_5S;
+          }
+          break;
+
+        case  PCIE_COMPLETION_TIMEOUT_RANGE_A_B_C_D_SUPPORTED:
+          if (IsCtoRangeA (PciDevice->SetupCTO.Support)
+              || IsCtoRangeB (PciDevice->SetupCTO.Support)
+              || IsCtoRangeC (PciDevice->SetupCTO.Support)
+              || IsCtoRangeD (PciDevice->SetupCTO.Support)
+          ) {
+            CtoRangeValue = PciDevice->SetupCTO.Support;
+          }
+          break;
+
+        default:
+          DEBUG ((
+              DEBUG_ERROR, "Invalid CTO range: %d\n",
+              DeviceCap2.Bits.CompletionTimeoutRanges
+          ));
+          return EFI_INVALID_PARAMETER;
+      }
+
+      if (PciDevice->SetupCTO.Support != CtoRangeValue) {
+        PciDevice->SetupCTO.Support = CtoRangeValue;
+      }
+    }
+    DEBUG (( DEBUG_INFO, "CTO enable: %d, CTO range: 0x%x,",
+        PciDevice->SetupCTO.Act,
+        PciDevice->SetupCTO.Support
+    ));
+  }
+  return EFI_SUCCESS;
+}
+
 /**
   Overrides the PCI Device Control register MaxPayloadSize register field; if
   the hardware value is different than the intended value.
@@ -1061,6 +1349,119 @@ OverrideNoSnoop (
   return Status;
 }
 
+/**
+  Overrides the PCI Device Control2 register Completion Timeout range; if
+  the hardware value is different than the intended value.
+
+  @param  PciDevice             A pointer to the PCI_IO_DEVICE instance.
+
+  @retval EFI_SUCCESS           The data was read from or written to the PCI device.
+  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width, and Count is not
+                                valid for the PCI configuration header of the PCI controller.
+  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
+
+**/
+EFI_STATUS
+OverrideCompletionTimeout (
+  IN PCI_IO_DEVICE          *PciDevice
+  )
+{
+  PCI_REG_PCIE_DEVICE_CONTROL2    DeviceCtl2;
+  PCI_REG_PCIE_DEVICE_CAPABILITY2 DeviceCap2;
+  UINT32                          Offset;
+  EFI_STATUS                      Status;
+  EFI_TPL                         OldTpl;
+
+  if (!PciDevice->SetupCTO.Override) {
+    //
+    // No override of CTO is required for this device
+    //
+    DEBUG (( DEBUG_INFO, "CTO skipped,"));
+    return  EFI_SUCCESS;
+  }
+
+  //
+  // to program the CTO range values, determine in its device capability register
+  //
+  DeviceCap2.Uint32 = PciDevice->PciExpStruct.DeviceCapability2.Uint32;
+  if (DeviceCap2.Bits.CompletionTimeoutRanges
+      || DeviceCap2.Bits.CompletionTimeoutDisable) {
+    //
+    // device supports the CTO mechanism
+    //
+    DeviceCtl2.Uint16 = 0;
+    Offset = PciDevice->PciExpressCapabilityOffset +
+              OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2);
+    Status = PciDevice->PciIo.Pci.Read (
+                                  &PciDevice->PciIo,
+                                  EfiPciIoWidthUint16,
+                                  Offset,
+                                  1,
+                                  &DeviceCtl2.Uint16
+                                  );
+    if (EFI_ERROR(Status)){
+      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl2 register (0x%x) read error!",
+                Offset
+      ));
+      return Status;
+    }
+  } else {
+    //
+    // device does not support the CTO mechanism, hence no override performed
+    //
+    DEBUG (( DEBUG_INFO, "CTO n/a,"));
+    return EFI_SUCCESS;
+  }
+
+  //
+  // override the device CTO values if applicable
+  //
+  if (PciDevice->SetupCTO.Act) {
+    //
+    // program the CTO range values
+    //
+    if (PciDevice->SetupCTO.Support != DeviceCtl2.Bits.CompletionTimeoutValue) {
+      DeviceCtl2.Bits.CompletionTimeoutValue = PciDevice->SetupCTO.Support;
+    }
+  } else {
+    //
+    // disable the CTO mechanism in device
+    //
+    DeviceCtl2.Bits.CompletionTimeoutValue = 0;
+    DeviceCtl2.Bits.CompletionTimeoutDisable = 1;
+  }
+  DEBUG (( DEBUG_INFO, "CTO disable: %d, CTO range: 0x%x,",
+      DeviceCtl2.Bits.CompletionTimeoutDisable,
+      DeviceCtl2.Bits.CompletionTimeoutValue
+  ));
+
+  //
+  // Raise TPL to high level to disable timer interrupt while the write operation completes
+  //
+  OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+  Status = PciDevice->PciIo.Pci.Write (
+                                &PciDevice->PciIo,
+                                EfiPciIoWidthUint16,
+                                Offset,
+                                1,
+                                &DeviceCtl2.Uint16
+                                );
+  //
+  // Restore TPL to its original level
+  //
+  gBS->RestoreTPL (OldTpl);
+
+  if (!EFI_ERROR(Status)) {
+    PciDevice->PciExpStruct.DeviceControl2.Uint16 = DeviceCtl2.Uint16;
+  } else {
+    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl2 register (0x%x) write error!",
+        Offset
+    ));
+  }
+  return Status;
+}
+
 /**
   helper routine to dump the PCIe Device Port Type
 **/
@@ -1169,6 +1570,15 @@ SetupDevicePciFeatures (
               OtherPciFeaturesConfigTable
               );
   }
+  //
+  // process the PCI device CTO range values to be configured
+  //
+  if (SetupCompletionTimeout ()) {
+    Status = ProcessCompletionTimeout (
+              PciDevice,
+              PciConfigPhase
+              );
+  }
   DEBUG ((DEBUG_INFO, "]\n"));
   return Status;
 }
@@ -1278,6 +1688,9 @@ ProgramDevicePciFeatures (
   if (SetupNoSnoop ()) {
     Status = OverrideNoSnoop (PciDevice);
   }
+  if (SetupCompletionTimeout()) {
+    Status = OverrideCompletionTimeout (PciDevice);
+  }
   DEBUG (( DEBUG_INFO, "\n"));
   return Status;
 }
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
index 47295cd..7ee0d7d 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
@@ -549,6 +549,85 @@ SetDevicePolicyNoSnoop (
   }
 }
 
+/**
+  Routine to set the device-specific policy for the PCI feature CTO value range
+  or disable
+
+  @param  CtoSupport    value corresponding to data type EFI_PCI_CONF_CTO_SUPPORT
+  @param  PciDevice     A pointer to PCI_IO_DEVICE
+**/
+VOID
+SetDevicePolicyCTO (
+  IN  EFI_PCI_CONF_CTO_SUPPORT    CtoSupport,
+  OUT PCI_IO_DEVICE               *PciDevice
+)
+{
+  //
+  // implementation specific rules for the usage of PCI_FEATURE_POLICY members
+  // exclusively for the PCI Feature CTO
+  //
+  // .Override = 0 to skip this PCI feature CTO for the PCI device
+  // .Override = 1 to program this CTO PCI feature
+  //      .Act = 1 to program the CTO range as per given device policy in .Support
+  //      .Act = 0 to disable the CTO mechanism in the PCI device, CTO set to default range
+  //
+  switch (CtoSupport) {
+    case  EFI_PCI_CONF_CTO_AUTO:
+      PciDevice->SetupCTO.Override = 0;
+      break;
+    case  EFI_PCI_CONF_CTO_DEFAULT:
+      PciDevice->SetupCTO.Override = 1;
+      PciDevice->SetupCTO.Act = 1;
+      PciDevice->SetupCTO.Support = PCIE_COMPLETION_TIMEOUT_50US_50MS;
+      break;
+    case  EFI_PCI_CONF_CTO_RANGE_A1:
+      PciDevice->SetupCTO.Override = 1;
+      PciDevice->SetupCTO.Act = 1;
+      PciDevice->SetupCTO.Support = PCIE_COMPLETION_TIMEOUT_50US_100US;
+      break;
+    case  EFI_PCI_CONF_CTO_RANGE_A2:
+      PciDevice->SetupCTO.Override = 1;
+      PciDevice->SetupCTO.Act = 1;
+      PciDevice->SetupCTO.Support = PCIE_COMPLETION_TIMEOUT_1MS_10MS;
+      break;
+    case  EFI_PCI_CONF_CTO_RANGE_B1:
+      PciDevice->SetupCTO.Override = 1;
+      PciDevice->SetupCTO.Act = 1;
+      PciDevice->SetupCTO.Support = PCIE_COMPLETION_TIMEOUT_16MS_55MS;
+      break;
+    case  EFI_PCI_CONF_CTO_RANGE_B2:
+      PciDevice->SetupCTO.Override = 1;
+      PciDevice->SetupCTO.Act = 1;
+      PciDevice->SetupCTO.Support = PCIE_COMPLETION_TIMEOUT_65MS_210MS;
+      break;
+    case  EFI_PCI_CONF_CTO_RANGE_C1:
+      PciDevice->SetupCTO.Override = 1;
+      PciDevice->SetupCTO.Act = 1;
+      PciDevice->SetupCTO.Support = PCIE_COMPLETION_TIMEOUT_260MS_900MS;
+      break;
+    case  EFI_PCI_CONF_CTO_RANGE_C2:
+      PciDevice->SetupCTO.Override = 1;
+      PciDevice->SetupCTO.Act = 1;
+      PciDevice->SetupCTO.Support = PCIE_COMPLETION_TIMEOUT_1S_3_5S;
+      break;
+    case  EFI_PCI_CONF_CTO_RANGE_D1:
+      PciDevice->SetupCTO.Override = 1;
+      PciDevice->SetupCTO.Act = 1;
+      PciDevice->SetupCTO.Support = PCIE_COMPLETION_TIMEOUT_4S_13S;
+      break;
+    case  EFI_PCI_CONF_CTO_RANGE_D2:
+      PciDevice->SetupCTO.Override = 1;
+      PciDevice->SetupCTO.Act = 1;
+      PciDevice->SetupCTO.Support = PCIE_COMPLETION_TIMEOUT_17S_64S;
+      break;
+    case  EFI_PCI_CONF_CTO_DET_DISABLE:
+      PciDevice->SetupCTO.Override = 1;
+      PciDevice->SetupCTO.Act = 0;
+      PciDevice->SetupCTO.Support = PCIE_COMPLETION_TIMEOUT_50US_50MS;
+      break;
+  }
+}
+
 /**
   Generic routine to setup the PCI features as per its predetermined defaults.
 **/
@@ -561,6 +640,7 @@ SetupDefaultsDevicePlatformPolicy (
   PciDevice->SetupMRRS = EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO;
   PciDevice->SetupRO.Override = 0;
   PciDevice->SetupNS.Override = 0;
+  PciDevice->SetupCTO.Override = 0;
 }
 
 /**
@@ -606,6 +686,10 @@ GetPciDevicePlatformPolicyEx (
       // set the device specific policy for No-Snoop
       //
       SetDevicePolicyNoSnoop (PciPlatformExtendedPolicy.DeviceCtlNoSnoop, PciIoDevice);
+      //
+      // set the device specific policy for Completion Timeout (CTO)
+      //
+      SetDevicePolicyCTO (PciPlatformExtendedPolicy.CTOsupport, PciIoDevice);
 
       DEBUG ((
           DEBUG_INFO, "[device policy: platform]"
-- 
2.21.0.windows.1


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe:New PCI features separation with PCD
       [not found] ` <15D3127A726D26A6.7420@groups.io>
@ 2019-11-13  3:22   ` Javeed, Ashraf
  2019-12-16 12:46     ` Ni, Ray
  0 siblings, 1 reply; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-13  3:22 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch is also uploaded in the following Repo:-
https://github.com/ashrafj/edk2-staging/commit/0cc1a9555e1546ad94dd368160ece526d10d96a6

Please review.
Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Friday, November 1, 2019 8:40 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12]
> MdeModulePkg/PciBusDxe:New PCI features separation with PCD
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> 
> Definition of bit masks for the new PCD for the following new PCI feature
> set:-
> 1.	Maximum Payload Size (MPS)
> 2.	Maximum Read Request Size (MRRS)
> 3.	Completion Timeout (CTO)
> 4.	Relax Order (RO) Enable
> 5.	No Snoop (NS) Enable
> 6.	Extended Tag
> 7.	ASPM support
> 8.	Common Clock Configuration
> 9.	Extended SYNC
> 10.	Atomic Op
> 11.	LTR Enable
> 12.	PTM support
> 
> Code changes made to the PCI Bus driver to adopt to these new PCD defini- tion,
> helper routines defined for features that needs to be supported in.
> future.
> 
> 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/PciBusDxe.inf       |   5 ++++-
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c | 177
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h |  26
> ++++++++++++++++++++++++++
>  MdeModulePkg/MdeModulePkg.dec                      |  22
> ++++++++++++++++++++++
>  4 files changed, 229 insertions(+), 1 deletion(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> index 05c2202..6dab970 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,8 @@
>    PciCommand.h
>    PciIo.h
>    PciBus.h
> +  PciFeatureSupport.c
> +  PciFeatureSupport.h
> 
>  [Packages]
>    MdePkg/MdePkg.dec
> @@ -104,6 +106,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/PciFeatureSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> new file mode 100644
> index 0000000..8be227a
> --- /dev/null
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> @@ -0,0 +1,177 @@
> +/** @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 "PciBus.h"
> +#include "PciFeatureSupport.h"
> +
> +/**
> +  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; }
> +
> +/**
> +  Main routine to indicate whether the platform has selected the Relax
> +Ordering
> +  PCI feature to be configured by this driver
> +
> +  @retval TRUE    platform has selected the Relax Ordering to be configured
> +          FALSE   platform has not selected this feature
> +**/
> +BOOLEAN
> +SetupRelaxOrder (
> +  )
> +{
> +  return (PcdGet32 (PcdOtherPciFeatures) & PCI_FEATURE_SUPPORT_FLAG_RO)
> +? TRUE : FALSE; }
> +
> +/**
> +  Main routine to indicate whether the platform has selected the
> +No-Snoop
> +  PCI feature to be configured by this driver
> +
> +  @retval TRUE    platform has selected the No-Snoop to be configured
> +          FALSE   platform has not selected this feature
> +**/
> +BOOLEAN
> +SetupNoSnoop (
> +  )
> +{
> +  return (PcdGet32 (PcdOtherPciFeatures) & PCI_FEATURE_SUPPORT_FLAG_NS)
> +? TRUE : FALSE; }
> +
> +/**
> +  Main routine to indicate whether the platform has selected the
> +Completion Timeout
> +  PCI feature to be configured by this driver
> +
> +  @retval TRUE    platform has selected the Completion Timeout to be
> configured
> +          FALSE   platform has not selected this feature
> +**/
> +BOOLEAN
> +SetupCompletionTimeout (
> +  )
> +{
> +  return (PcdGet32 (PcdOtherPciFeatures) &
> +PCI_FEATURE_SUPPORT_FLAG_CTO) ? TRUE : FALSE; }
> +
> +/**
> +  Main routine to indicate whether the platform has selected the
> +Extended Tag
> +  PCI feature to be configured by this driver
> +
> +  @retval TRUE    platform has selected the Completion Timeout to be
> configured
> +          FALSE   platform has not selected this feature
> +**/
> +BOOLEAN
> +SetupExtendedTag (
> +  )
> +{
> +  return (PcdGet32 (PcdOtherPciFeatures) &
> +PCI_FEATURE_SUPPORT_FLAG_ETAG) ? TRUE : FALSE; }
> +
> +/**
> +  Main routine to indicate whether the platform has selected the Atomic
> +Op
> +  PCI feature to be configured by this driver
> +
> +  @retval TRUE    platform has selected the Completion Timeout to be
> configured
> +          FALSE   platform has not selected this feature
> +**/
> +BOOLEAN
> +SetupAtomicOp (
> +  )
> +{
> +  return (PcdGet32 (PcdOtherPciFeatures) &
> +PCI_FEATURE_SUPPORT_FLAG_AOP) ? TRUE : FALSE; }
> +/**
> +  Main routine to indicate whether the platform has selected the LTR
> +  PCI feature to be configured by this driver
> +
> +  @retval TRUE    platform has selected the Completion Timeout to be
> configured
> +          FALSE   platform has not selected this feature
> +**/
> +BOOLEAN
> +SetupLtr (
> +  )
> +{
> +  return (PcdGet32 (PcdOtherPciFeatures) &
> +PCI_FEATURE_SUPPORT_FLAG_LTR) ? TRUE : FALSE; }
> +
> +/**
> +  Main routine to indicate whether the platform has selected the ASPM
> +state
> +  PCI feature to be configured by this driver
> +
> +  @retval TRUE    platform has selected the Completion Timeout to be
> configured
> +          FALSE   platform has not selected this feature
> +**/
> +BOOLEAN
> +SetupAspm (
> +  )
> +{
> +  return (PcdGet32 (PcdOtherPciFeatures) &
> +PCI_FEATURE_SUPPORT_FLAG_ASPM) ? TRUE : FALSE; }
> +
> +/**
> +  Main routine to indicate whether the platform has selected the Common
> +Clock Configuration
> +  PCI feature to be configured by this driver
> +
> +  @retval TRUE    platform has selected the Completion Timeout to be
> configured
> +          FALSE   platform has not selected this feature
> +**/
> +BOOLEAN
> +SetupCommonClkCfg (
> +  )
> +{
> +  return (PcdGet32 (PcdOtherPciFeatures) &
> +PCI_FEATURE_SUPPORT_FLAG_CCC) ? TRUE : FALSE; }
> +
> +/**
> +  Main routine to indicate whether the platform has selected the
> +Extended Synch
> +  PCI feature to be configured by this driver
> +
> +  @retval TRUE    platform has selected the Completion Timeout to be
> configured
> +          FALSE   platform has not selected this feature
> +**/
> +BOOLEAN
> +SetupExtendedSynch (
> +  )
> +{
> +  return (PcdGet32 (PcdOtherPciFeatures) &
> +PCI_FEATURE_SUPPORT_FLAG_ESYN) ? TRUE : FALSE; }
> +
> +/**
> +  Main routine to indicate whether the platform has selected the PIM
> +Control
> +  PCI feature to be configured by this driver
> +
> +  @retval TRUE    platform has selected the Completion Timeout to be
> configured
> +          FALSE   platform has not selected this feature
> +**/
> +BOOLEAN
> +SetupPtm (
> +  )
> +{
> +  return (PcdGet32 (PcdOtherPciFeatures) &
> +PCI_FEATURE_SUPPORT_FLAG_PTM) ? TRUE : FALSE; }
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> new file mode 100644
> index 0000000..d06a5e8
> --- /dev/null
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> @@ -0,0 +1,26 @@
> +/** @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_
> +//
> +// Macro definitions for the PCI Features support PCD // #define
> +PCI_FEATURE_SUPPORT_FLAG_MPS  BIT0 #define
> +PCI_FEATURE_SUPPORT_FLAG_MRRS BIT1
> +#define PCI_FEATURE_SUPPORT_FLAG_RO   BIT2
> +#define PCI_FEATURE_SUPPORT_FLAG_NS   BIT3
> +#define PCI_FEATURE_SUPPORT_FLAG_CTO  BIT4 #define
> +PCI_FEATURE_SUPPORT_FLAG_ETAG BIT5 #define
> PCI_FEATURE_SUPPORT_FLAG_AOP
> +BIT6 #define PCI_FEATURE_SUPPORT_FLAG_LTR  BIT7 #define
> +PCI_FEATURE_SUPPORT_FLAG_ASPM BIT12 #define
> +PCI_FEATURE_SUPPORT_FLAG_CCC  BIT13 #define
> +PCI_FEATURE_SUPPORT_FLAG_ESYN BIT14 #define
> +PCI_FEATURE_SUPPORT_FLAG_PTM  BIT20 #endif
> diff --git a/MdeModulePkg/MdeModulePkg.dec
> b/MdeModulePkg/MdeModulePkg.dec index 12e0bbf..ed82e85 100644
> --- a/MdeModulePkg/MdeModulePkg.dec
> +++ b/MdeModulePkg/MdeModulePkg.dec
> @@ -1036,6 +1036,28 @@
>    # @Prompt Enable UEFI Stack Guard.
> 
> gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard|FALSE|BOOLEAN|0x30
> 001055
> 
> +  ## 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 - if set, the PCI Bus driver programs the device's Relax Ordering
> state.<BR>
> +  #   Bit 3 - if set, the PCI Bus driver programs the device's No-Snoop state.<BR>
> +  #   Bit 4 - if set, the PCI Bus driver programs the device's Completion Timeout
> range.<BR>
> +  #   Bit 5 - if set, the PCI Bus driver programs the device's Extended Tag
> range.<BR>
> +  #   Bit 6 - if set, the PCI Bus driver programs the device's AtomicOp
> feature.<BR>
> +  #   Bit 7 - if set, the PCI Bus driver programs the device's LTR feature.<BR>
> +  #   Bit 8 to 11 - Reserved for future use by the PCI Bus driver.<BR>
> +  #   Bit 12 - if set, the PCI Bus driver programs the PCIe link ASPM state.<BR>
> +  #   Bit 13 - if set, the PCI Bus driver programs the PCIe link Common Clock
> Configuration.<BR>
> +  #   Bit 14 - if set, the PCI Bus driver programs the PCIe link Extended Synch
> state.<BR>
> +  #   Bit 15 to 19 - Reserved for future use by the PCI Bus driver.<BR>
> +  #   Bit 20 - if set, the PCI Bus driver programs the device's PTM feature.<BR>
> +  #   Bit 21 to 31 - Reserved for future use by the PCI Bus driver.<BR>
> +  # @Prompt The UEFI PCI Bus driver enables the new set of other PCI Features.
> +
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures|0x001070FF|UINT32|
> 0
> + x30001056
> +
>  [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	[flat|nested] 51+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12] PciBusDxe: Reorganize the PCI Platform Protocol usage code
       [not found] ` <15D3127AABF5037C.32624@groups.io>
@ 2019-11-13  3:23   ` Javeed, Ashraf
  2019-12-16 12:46     ` Ni, Ray
  0 siblings, 1 reply; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-13  3:23 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch is also uploaded in the following Repo, for review:-
https://github.com/ashrafj/edk2-staging/commit/ff68bb88bdb81d3921ebc7410c69e52e9d2fdb0e

Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Friday, November 1, 2019 8:40 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12]
> PciBusDxe: Reorganize the PCI Platform Protocol usage code
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> 
> The following legacy PCI Platform Protocol usage is reorganized in the separate
> source files:-
> (1) PlatformPrepController
> (2) PlatformNotify
> (3) GetPlatformPolicy
> (4) GetPciRom
> 
> This code changes are made to support the new PCI Platform Protocol along
> with the existing legacy interface in the PCI Bus driver.
> 
> 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             |   3 +--
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf        |   2 ++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c   |  58 +++++++++++-----
> ------------------------------------------
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c      | 139
> +++++++++++++++++++++++++++++++++------------------------------------------------
> ----------------------------------------------------------
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 254
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h | 109
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c |  15 +--------------
>  8 files changed, 413 insertions(+), 190 deletions(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> index b020ce5..45cd64d 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
> -          );
> -  }
> +  LocatePciPlatformProtocol ();
> 
>    if (mIoMmuProtocol == NULL) {
>      gBS->LocateProtocol (
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> index 504a1b1..141c158 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> @@ -79,6 +79,7 @@ typedef enum {
>  #include "PciPowerManagement.h"
>  #include "PciHotPlugSupport.h"
>  #include "PciLib.h"
> +#include "PciPlatformSupport.h"
> 
>  #define VGABASE1  0x3B0
>  #define VGALIMIT1 0x3BB
> @@ -307,8 +308,6 @@ extern UINTN
> gPciHostBridgeNumber;
>  extern EFI_HANDLE
> gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM];
>  extern UINT64                                       gAllOne;
>  extern UINT64                                       gAllZero;
> -extern EFI_PCI_PLATFORM_PROTOCOL                    *gPciPlatformProtocol;
> -extern EFI_PCI_OVERRIDE_PROTOCOL                    *gPciOverrideProtocol;
>  extern BOOLEAN                                      mReserveIsaAliases;
>  extern BOOLEAN                                      mReserveVgaAliases;
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> index 6dab970..4ce99ce 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> @@ -59,6 +59,8 @@
>    PciBus.h
>    PciFeatureSupport.c
>    PciFeatureSupport.h
> +  PciPlatformSupport.c
> +  PciPlatformSupport.h
> 
>  [Packages]
>    MdePkg/MdePkg.dec
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> index b7832c6..149a120 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> @@ -208,8 +208,6 @@ RegisterPciDevice (
>    )
>  {
>    EFI_STATUS          Status;
> -  VOID                *PlatformOpRomBuffer;
> -  UINTN               PlatformOpRomSize;
>    EFI_PCI_IO_PROTOCOL *PciIo;
>    UINT8               Data8;
>    BOOLEAN             HasEfiImage;
> @@ -244,49 +242,16 @@ 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 +259,7 @@ RegisterPciDevice (
>            PciIoDevice->FunctionNumber,
>            PciIoDevice->PciIo.RomImage,
>            PciIoDevice->PciIo.RomSize
> -          );
> -      }
> +        );
>      }
>    }
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> index 8db1ebf..aef8a3b 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/PciPlatformSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> new file mode 100644
> index 0000000..6f95794
> --- /dev/null
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> @@ -0,0 +1,254 @@
> +/** @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 "PciBus.h"
> +
> +EFI_PCI_PLATFORM_PROTOCOL                     *mPciPlatformProtocol;
> +EFI_PCI_OVERRIDE_PROTOCOL                     *mPciOverrideProtocol;
> +
> +
> +
> +/**
> +  This function retrieves the PCI Platform Protocol published by
> +platform driver
> +
> +**/
> +VOID
> +LocatePciPlatformProtocol (
> +  )
> +{
> +    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 (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 (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 (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 (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 (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;
> +}
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> new file mode 100644
> index 0000000..c0d3b49
> --- /dev/null
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> @@ -0,0 +1,109 @@
> +/** @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_
> +
> +/**
> +  This function retrieves the PCI Platform Protocol published by
> +platform driver
> +
> +**/
> +VOID
> +LocatePciPlatformProtocol (
> +  );
> +
> +/**
> +  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
> +  );
> +
> +#endif
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> index 4969ee0..be6f42a 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;
> --
> 2.21.0.windows.1
> 
> 
> 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12] PciBusDxe: Separation of the PCI device registration and start
       [not found] ` <15D3127A98E21087.7420@groups.io>
@ 2019-11-13  3:25   ` Javeed, Ashraf
  2019-12-17  1:38     ` Ni, Ray
  0 siblings, 1 reply; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-13  3:25 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch is also uploaded in following Repo, for review:-
https://github.com/ashrafj/edk2-staging/commit/421511cd582975c65983d75dad0e2a58956bfafd

Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Friday, November 1, 2019 8:40 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12]
> PciBusDxe: Separation of the PCI device registration and start
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> 
> The separation of the PCI device registration phase includes only the installation
> of the PCI IO Protocol on the PCI node to acquire the EFI handles, and loading of
> its applicable PCI Option ROM.
> 
> The separation of the PCI device start phase only includes the code that enables
> the PCI Bridge device as a Bus Master.
> 
> This code change is made in order to introduce the enabling of the other PCI
> features in the PCI Bus driver.
> 
> Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> ---
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c | 164
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ----------------------------------
>  1 file changed, 130 insertions(+), 34 deletions(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> index 149a120..33a0e94 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> @@ -561,7 +561,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.
> @@ -576,7 +576,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,
> @@ -590,7 +665,6 @@ StartPciDevicesOnBridge (
>    EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;
>    EFI_STATUS                Status;
>    LIST_ENTRY                *CurrentLink;
> -  UINT64                    Supports;
> 
>    PciIoDevice = NULL;
>    CurrentLink = RootBridge->ChildList.ForwardLink;
> @@ -645,7 +719,7 @@ StartPciDevicesOnBridge (
>        // If it is a PPB
>        //
>        if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
> -        Status = StartPciDevicesOnBridge (
> +        Status = RegisterPciDevicesOnBridge (
>                     Controller,
>                     PciIoDevice,
>                     CurrentDevicePath,
> @@ -653,20 +727,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 {
> 
> @@ -697,28 +757,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; @@ -732,6 +777,57 @@
> 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 {
> +    //
> +    // 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.
> --
> 2.21.0.windows.1
> 
> 
> 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 04/12] PciBusDxe: Inclusion of new PCI Platform Protocol 2
       [not found] ` <15D3127AAE5DC481.32624@groups.io>
@ 2019-11-13  3:26   ` Javeed, Ashraf
  0 siblings, 0 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-13  3:26 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch is also uploaded in the following Repo, for review:-
https://github.com/ashrafj/edk2-staging/commit/bcaab03c212a8d6c3e23ab986aa3ec05b60dd61d

Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Friday, November 1, 2019 8:40 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 04/12]
> PciBusDxe: Inclusion of new PCI Platform Protocol 2
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> 
> The code changes are made to support the new PCI Platform Protocol, as well
> as the legacy PCI Platform Protocol interfaces.
> 
> The code change is made to consume the new interface to acquire the PCI
> device-specific platform policy.
> 
> This code change is made to support the enabling of the other PCI features in
> the PCI Bus driver.
> 
> Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> ---
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h             |   2 ++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf        |   2 ++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 208
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++--
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h |  18
> ++++++++++++++++++
>  4 files changed, 228 insertions(+), 2 deletions(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> index 141c158..95a677b 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> diff --git
> a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> index 4ce99ce..44dec53 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> @@ -95,6 +95,8 @@
>    gEfiLoadFile2ProtocolGuid                       ## SOMETIMES_PRODUCES
>    gEdkiiIoMmuProtocolGuid                         ## SOMETIMES_CONSUMES
>    gEfiLoadedImageDevicePathProtocolGuid           ## CONSUMES
> +  gEfiPciPlatformProtocol2Guid                     ## SOMETIMES_CONSUMES
> +  gEfiPciOverrideProtocol2Guid                     ## SOMETIMES_CONSUMES
> 
>  [FeaturePcd]
>    gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport      ##
> CONSUMES
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> index 6f95794..238959e 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> @@ -14,6 +14,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
>  EFI_PCI_PLATFORM_PROTOCOL                     *mPciPlatformProtocol;
>  EFI_PCI_OVERRIDE_PROTOCOL                     *mPciOverrideProtocol;
> 
> +EFI_PCI_PLATFORM_PROTOCOL2                    *mPciPlatformProtocol2;
> +EFI_PCI_OVERRIDE_PROTOCOL2                    *mPciOverrideProtocol2;
> 
> 
>  /**
> @@ -24,6 +26,29 @@ VOID
>  LocatePciPlatformProtocol (
>    )
>  {
> +  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,
> @@ -42,6 +67,7 @@ LocatePciPlatformProtocol (
>            (VOID **) &mPciOverrideProtocol
>        );
>      }
> +  }
>  }
> 
>  /**
> @@ -52,13 +78,17 @@ 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;
>  }
> 
> @@ -90,6 +120,32 @@ PciPlatformPreprocessController (
>    )
>  {
>    EFI_STATUS  Status;
> +
> +  if (mPciPlatformProtocol2 != NULL) {
> +    //
> +    // Call PlatformPci::PrepController() if the protocol is present.
> +    //
> +    Status = mPciPlatformProtocol2->PlatformPrepController (
> +                                      mPciPlatformProtocol2,
> +                                      HostBridgeHandle,
> +                                      RootBridgeHandle,
> +                                      RootBridgePciAddress,
> +                                      Phase,
> +                                      ExecPhase
> +                                    );
> +  } else if (mPciOverrideProtocol2 != NULL) {
> +    //
> +    // Call PlatformPci::PrepController() if the protocol is present.
> +    //
> +    Status = mPciOverrideProtocol2->PlatformPrepController (
> +                                      mPciOverrideProtocol2,
> +                                      HostBridgeHandle,
> +                                      RootBridgeHandle,
> +                                      RootBridgePciAddress,
> +                                      Phase,
> +                                      ExecPhase
> +                                    );
> +  } else {
>      if (mPciPlatformProtocol != NULL) {
>        //
>        // Call PlatformPci::PrepController() if the protocol is present.
> @@ -120,6 +176,7 @@ PciPlatformPreprocessController (
>        //
>        return EFI_NOT_FOUND;
>      }
> +  }
>    return Status;
>  }
> 
> @@ -142,6 +199,21 @@ PciPlatformNotifyPhase (  {
>    EFI_STATUS  Status;
> 
> +  if (mPciPlatformProtocol2 != NULL) {
> +    Status = mPciPlatformProtocol2->PlatformNotify (
> +                                      mPciPlatformProtocol2,
> +                                      HostBridgeHandle,
> +                                      Phase,
> +                                      ExecPhase
> +                                    );
> +  } else if (mPciOverrideProtocol2 != NULL) {
> +    Status = mPciOverrideProtocol2->PlatformNotify (
> +                                      mPciOverrideProtocol2,
> +                                      HostBridgeHandle,
> +                                      Phase,
> +                                      ExecPhase
> +                                    );
> +  } else {
> 
>      if (mPciPlatformProtocol != NULL) {
>        Status = mPciPlatformProtocol->PlatformNotify ( @@ -163,6 +235,7 @@
> PciPlatformNotifyPhase (
>        //
>        return EFI_NOT_FOUND;
>      }
> +  }
>    return Status;
>  }
> 
> @@ -179,6 +252,18 @@ PciGetPlatformPolicy (
>    )
>  {
>    EFI_STATUS  Status;
> +
> +  if (mPciPlatformProtocol2 != NULL) {
> +      Status = mPciPlatformProtocol2->GetPlatformPolicy (
> +                                        mPciPlatformProtocol2,
> +                                        PciPolicy
> +                                      );  } else if
> + (mPciOverrideProtocol2 != NULL) {
> +      Status = mPciOverrideProtocol2->GetPlatformPolicy (
> +                                        mPciOverrideProtocol2,
> +                                        PciPolicy
> +                                      );  } else {
>      if (mPciPlatformProtocol != NULL) {
>        Status = mPciPlatformProtocol->GetPlatformPolicy (
>                                        mPciPlatformProtocol, @@ -197,6 +282,7 @@
> PciGetPlatformPolicy (
>        //
>        return EFI_NOT_FOUND;
>      }
> +  }
>    return Status;
>  }
> 
> @@ -223,6 +309,22 @@ GetPlatformPciOptionRom (
>    EFI_STATUS  Status;
>    VOID        *PlatformOpRomBuffer;
>    UINTN       PlatformOpRomSize;
> +
> +  if (mPciPlatformProtocol2 != NULL) {
> +    Status = mPciPlatformProtocol2->GetPciRom (
> +                                      mPciPlatformProtocol2,
> +                                      PciIoDevice->Handle,
> +                                      &PlatformOpRomBuffer,
> +                                      &PlatformOpRomSize
> +                                      );  } else if
> + (mPciOverrideProtocol2 != NULL) {
> +    Status = mPciOverrideProtocol2->GetPciRom (
> +                                      mPciOverrideProtocol2,
> +                                      PciIoDevice->Handle,
> +                                      &PlatformOpRomBuffer,
> +                                      &PlatformOpRomSize
> +                                      );  } else {
>      if (mPciPlatformProtocol != NULL) {
>        Status = mPciPlatformProtocol->GetPciRom (
>                                        mPciPlatformProtocol, @@ -243,6 +345,7 @@
> GetPlatformPciOptionRom (
>        //
>        return EFI_NOT_FOUND;
>      }
> +  }
> 
>    if (!EFI_ERROR (Status)) {
>      PciIoDevice->EmbeddedRom    = FALSE;
> @@ -252,3 +355,104 @@ GetPlatformPciOptionRom (
>    }
>    return Status;
>  }
> +
> +/**
> +  Generic routine to setup the PCI features as per its predetermined defaults.
> +**/
> +VOID
> +SetupDefaultsDevicePlatformPolicy (
> +  IN  PCI_IO_DEVICE               *PciDevice
> +  )
> +{
> +}
> +
> +/**
> +  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
> +                                  );
> +  switch (Status) {
> +    case  EFI_SUCCESS:
> +      //
> +      // platform chipset policies are returned for this PCI device
> +      //
> +
> +      DEBUG ((
> +          DEBUG_INFO, "[device policy: platform]"
> +      ));
> +      return Status;
> +
> +    case  EFI_UNSUPPORTED:
> +      //
> +      // platform chipset policies are not provided for this PCI device
> +      // let the enumeration happen as per the PCI standard way
> +      //
> +      SetupDefaultsDevicePlatformPolicy (PciIoDevice);
> +      DEBUG ((
> +          DEBUG_INFO, "[device policy: default]"
> +      ));
> +      return EFI_SUCCESS;
> +
> +    default:
> +      DEBUG ((
> +          DEBUG_ERROR, "[device policy: none (error)]"
> +      ));
> +      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
> index c0d3b49..a13131c 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> @@ -106,4 +106,22 @@ GetPlatformPciOptionRom (
>    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
> +  );
>  #endif
> --
> 2.21.0.windows.1
> 
> 
> 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
       [not found] ` <15D3127B934F51D3.12315@groups.io>
@ 2019-11-13  3:27   ` Javeed, Ashraf
  2019-12-17 11:56     ` Ni, Ray
  0 siblings, 1 reply; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-13  3:27 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch is also uploaded in the following Repo for review:-
https://github.com/ashrafj/edk2-staging/commit/59854e2f4eb2b52c9e73f9c5c7fede6c5128b39a

Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Friday, November 1, 2019 8:40 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12]
> PciBusDxe: Setup sub-phases for PCI feature enumeration
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> 
> The code changes are made to setup the following internal sub-phases for
> enumerating the PCI features in the late phase of the PCI Bus driver.
> (1) PciFeatureRootBridgeScan - initial phase in configuring the other PCI
>     features to record the primary root ports
> (2) PciFeatureGetDevicePolicy - get the PCI device-specific platform pol-
>     icies and align with device capabilities
> (3) PciFeatureSetupPhase - align all PCI nodes in the PCI heirarchical
>     tree (if required for that PCI feature)
> (4) PciFeatureConfigurationPhase - finally override to complete configu-
>     ration of the PCI feature
> 
> The code changes are made to support the configuration of other PCIe features,
> like MPS, which require a common value to be assigned among all the child PCI
> devices and its parent root port device.
> 
> 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/PciFeatureSupport.c | 859
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h | 146
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ++++++++++++++++
>  2 files changed, 1005 insertions(+)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> index 8be227a..ab0e096 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> @@ -9,6 +9,23 @@ SPDX-License-Identifier: BSD-2-Clause-Patent  #include
> "PciBus.h"
>  #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 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 whether the platform has selected the
> Max_Payload_Size
>    PCI feature to be configured by this driver @@ -175,3 +192,845 @@ SetupPtm
> (  {
>    return (PcdGet32 (PcdOtherPciFeatures) &
> PCI_FEATURE_SUPPORT_FLAG_PTM) ? TRUE : FALSE;  }
> +
> +/**
> + Helper routine to determine the existence of previously enumerated PCI
> +device
> +
> + @retval  TRUE  PCI device exist
> +          FALSE does not exist
> +**/
> +BOOLEAN
> +DeviceExist (
> +  PCI_IO_DEVICE                   *PciDevice
> +  )
> +{
> +  EFI_PCI_IO_PROTOCOL   *PciIoProtocol = &PciDevice->PciIo;
> +  UINT16                VendorId = 0xFFFF;
> +
> +  PciIoProtocol->Pci.Read (
> +                      PciIoProtocol,
> +                      EfiPciIoWidthUint16,
> +                      PCI_VENDOR_ID_OFFSET,
> +                      1,
> +                      &VendorId
> +                      );
> +  if (VendorId == 0 || VendorId == 0xFFFF) {
> +    return FALSE;
> +  } else {
> +    return TRUE;
> +  }
> +}
> +
> +/**
> +  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 == NULL) {
> +      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->OtherPciFeaturesConfigurationTable);
> +      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->OtherPciFeaturesConfigurationTable);
> +        FreePool (Temp);
> +      } while (!IsListEmpty (Link));
> +      FreePool (mPrimaryRootPortList->OtherPciFeaturesConfigurationTable);
> +      FreePool (mPrimaryRootPortList);
> +    }
> +    mPrimaryRootPortList = 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 ();
> +  }
> +}
> +
> +/**
> +  Main routine to determine the child PCI devices of a PCI bridge
> +device
> +  and group them under a common internal PCI features Configuration table.
> +
> +  @param  PciDevice                       A pointer to the PCI_IO_DEVICE.
> +  @param  PciFeaturesConfigTable          A pointer to a pointer to the
> +                                          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 PCI bus range
> + (not a child)
> +
> +  @retval EFI_SUCCESS                     able to determine the PCI feature
> +                                          configuration table. For RCiEP since
> +                                          since it is not prepared.
> +          EFI_DEVICE_ERROR                the PCI device has invalid EFI device
> +                                          path **/ EFI_STATUS
> +GetPciFeaturesConfigurationTable (
> +  IN  PCI_IO_DEVICE                           *PciDevice,
> +  OUT OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> **PciFeaturesConfigTable
> +  )
> +{
> +  LIST_ENTRY                *Link;
> +  PRIMARY_ROOT_PORT_NODE    *Temp;
> +  BOOLEAN                   NodeMatch;
> +  EFI_DEVICE_PATH_PROTOCOL  *RootPortPath;
> +  EFI_DEVICE_PATH_PROTOCOL  *PciDevicePath;
> +
> +  if (mPrimaryRootPortList == NULL) {
> +    //
> +    // no populated PCI primary root ports to parse and match the PCI features
> +    // configuration table
> +    //
> +    *PciFeaturesConfigTable = NULL;
> +    return EFI_SUCCESS;
> +  }
> +
> +
> +  if (IsDevicePathEnd (PciDevice->DevicePath)){
> +    //
> +    // the given PCI device does not have a valid device path
> +    //
> +    *PciFeaturesConfigTable = NULL;
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +
> +  Link = &mPrimaryRootPortList->NeighborRootPort;
> +  do {
> +    Temp = PRIMARY_ROOT_PORT_NODE_FROM_LINK (Link);
> +    RootPortPath = Temp->RootPortDevicePath;
> +    PciDevicePath = PciDevice->DevicePath;
> +    NodeMatch = FALSE;
> +    //
> +    // match the device path from the list of primary Root Ports with the given
> +    // device; the initial nodes matching in sequence indicate that the given PCI
> +    // device belongs to that PCI tree from the root port
> +    //
> +    if (IsDevicePathEnd (RootPortPath)) {
> +      //
> +      // critical error as no device path available in root
> +      //
> +      *PciFeaturesConfigTable = NULL;
> +      return EFI_DEVICE_ERROR;
> +    }
> +
> +    if (EfiCompareDevicePath (RootPortPath, PciDevicePath)) {
> +      //
> +      // the given PCI device is the primary root port itself
> +      //
> +      *PciFeaturesConfigTable = Temp->OtherPciFeaturesConfigurationTable;
> +      return EFI_SUCCESS;
> +    }
> +    //
> +    // check this PCI device belongs to the primary root port of the root bridge
> +    // any child PCI device will have the same initial device path nodes  as
> +    // its parent root port
> +    //
> +    while (!IsDevicePathEnd (RootPortPath)){
> +
> +      if (DevicePathNodeLength (RootPortPath) != DevicePathNodeLength
> (PciDevicePath)) {
> +        //
> +        // break to check the next primary root port nodes as does not match
> +        //
> +        NodeMatch = FALSE;
> +        break;
> +      }
> +      if (CompareMem (RootPortPath, PciDevicePath, DevicePathNodeLength
> (RootPortPath)) != 0) {
> +        //
> +        // node does not match, break to check next node
> +        //
> +        NodeMatch = FALSE;
> +        break;
> +      }
> +      NodeMatch = TRUE;
> +      //
> +      // advance to next node
> +      //
> +      RootPortPath = NextDevicePathNode (RootPortPath);
> +      PciDevicePath = NextDevicePathNode (PciDevicePath);
> +    }
> +
> +    if (NodeMatch == TRUE) {
> +      //
> +      // device belongs to primary root port, return its PCI feature configuration
> +      // table
> +      //
> +      *PciFeaturesConfigTable = Temp->OtherPciFeaturesConfigurationTable;
> +      return EFI_SUCCESS;
> +    }
> +
> +    //
> +    // advance to next Root port node
> +    //
> +    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;
> +}
> +
> +/**
> +  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
> +  )
> +{
> +  if (IsListEmpty (&PciDevice->ChildList)){
> +    return TRUE;
> +  }
> +  return FALSE;
> +}
> +
> +
> +/**
> +   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;
> +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> *OtherPciFeaturesConfigTable;
> +
> +  OtherPciFeaturesConfigTable = NULL;
> +  Status = GetPciFeaturesConfigurationTable (PciDevice,
> + &OtherPciFeaturesConfigTable);  if (EFI_ERROR( Status)) {
> +    DEBUG ((
> +       DEBUG_WARN, "[Cfg group: 0 {error in dev path}]"
> +    ));
> +  } else if (OtherPciFeaturesConfigTable == NULL) {
> +    DEBUG ((
> +        DEBUG_INFO, "[Cfg group: 0]"
> +    ));
> +  } else {
> +    DEBUG ((
> +        DEBUG_INFO, "[Cfg group: %d]",
> +        OtherPciFeaturesConfigTable->ID
> +    ));
> +  }
> +
> +  if (PciConfigPhase == PciFeatureGetDevicePolicy) {
> +    Status = GetPciDevicePlatformPolicy (PciDevice);
> +    if (EFI_ERROR(Status)) {
> +      DEBUG ((
> +          DEBUG_ERROR, "Error in obtaining PCI device policy!!!\n"
> +      ));
> +    }
> +  }
> +
> +  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 (!DeviceExist (Device)) {
> +      DEBUG ((
> +          DEBUG_ERROR, "::Device [%02x|%02x|%02x] - does not exist!!!\n",
> +          Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
> +      ));
> +      continue;
> +    }
> +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> +      DEBUG ((
> +          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
> +          Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
> +      ));
> +      if (Device->IsPciExp) {
> +        Status = 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;
> +
> +  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 (!DeviceExist (Device)) {
> +      DEBUG ((
> +          DEBUG_ERROR, "::Device [%02x|%02x|%02x] - does not exist!!!\n",
> +          Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
> +      ));
> +      continue;
> +    }
> +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> +      DEBUG ((
> +          DEBUG_INFO, "::Bridge [%02x|%02x|%02x] -",
> +          Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber
> +      ));
> +      if (Device->IsPciExp) {
> +        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 and add a node of type PRIMARY_ROOT_PORT_NODE in the list for
> +the primary
> +  Root Port so that all its child PCI devices can be identified against
> +the PCI
> +  features configuration table group ID, of type
> OTHER_PCI_FEATURES_CONFIGURATION_TABLE.
> +
> +  @param BridgePort    A pointer to the PCI_IO_DEVICE
> +  @param PortNumber    A UINTN value to identify the PCI feature
> configuration
> +                       table group
> +
> +  @retval EFI_SUCCESS           success in adding a node of
> PRIMARY_ROOT_PORT_NODE
> +                                to the list
> +          EFI_OUT_OF_RESOURCES  unable to get memory for creating the
> +node **/ EFI_STATUS AddPrimaryRootPortNode (
> +  IN  PCI_IO_DEVICE           *BridgePort,
> +  IN  UINTN                   PortNumber
> +  )
> +{
> +  PRIMARY_ROOT_PORT_NODE                  *RootPortNode = NULL;
> +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE  *PciConfigTable = NULL;
> +
> +  RootPortNode = AllocateZeroPool (sizeof (PRIMARY_ROOT_PORT_NODE));
> + if (RootPortNode == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  RootPortNode->Signature                           = PCI_ROOT_PORT_SIGNATURE;
> +  RootPortNode->RootPortDevicePath                  = BridgePort->DevicePath;
> +  PciConfigTable = AllocateZeroPool (
> +                     sizeof (OTHER_PCI_FEATURES_CONFIGURATION_TABLE)
> +                    );
> +  if (PciConfigTable) {
> +    PciConfigTable->ID                          = PortNumber;
> +  }
> +  RootPortNode->OtherPciFeaturesConfigurationTable  = PciConfigTable;
> +
> +  if (mPrimaryRootPortList != NULL) {
> +    InsertTailList (&mPrimaryRootPortList->NeighborRootPort,
> + &RootPortNode->NeighborRootPort);  } else {
> +    InitializeListHead (&RootPortNode->NeighborRootPort);
> +    mPrimaryRootPortList = RootPortNode;  }
> +
> +  if (PciConfigTable == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Scan all the nodes of the RootBridge to identify and create a
> +separate list
> +  of all primary physical PCI root ports and link each with its own
> +instance of
> +  the PCI Feature Configuration Table.
> +
> +  @param  RootBridge    A pointer to the PCI_IO_DEVICE of the PCI Root Bridge
> +
> +  @retval EFI_OUT_OF_RESOURCES  unable to allocate buffer to store PCI
> feature
> +                                configuration table for all the physical PCI root
> +                                ports given
> +          EFI_NOT_FOUND         No PCI Bridge device found
> +          EFI_SUCCESS           PCI Feature COnfiguration table created for all
> +                                the PCI Rooot ports found
> +          EFI_INVALID_PARAMETER invalid parameter passed to the routine which
> +                                creates the PCI controller node for the primary
> +                                Root post list **/ EFI_STATUS
> +RecordPciRootPortBridges (
> +  IN  PCI_IO_DEVICE           *RootBridge
> +  )
> +{
> +  EFI_STATUS              Status = EFI_NOT_FOUND;
> +  LIST_ENTRY              *Link;
> +  PCI_IO_DEVICE           *Device;
> +  UINTN                   NumberOfRootPorts;
> +
> +  DEBUG ((
> +      DEBUG_INFO, "<<********** RecordPciRootPortBridges -start
> *************>>\n"
> +  ));
> +  NumberOfRootPorts = 0;
> +  for ( Link = RootBridge->ChildList.ForwardLink
> +      ; Link != &RootBridge->ChildList
> +      ; Link = Link->ForwardLink
> +  ) {
> +    Device = PCI_IO_DEVICE_FROM_LINK (Link);
> +    if (!DeviceExist (Device)) {
> +      continue;
> +    }
> +    if (IS_PCI_BRIDGE (&Device->Pci)) {
> +      NumberOfRootPorts++;
> +      DEBUG ((
> +          DEBUG_INFO, "#%d ::Bridge [%02x|%02x|%02x]",
> +          NumberOfRootPorts, Device->BusNumber, Device->DeviceNumber,
> Device->FunctionNumber
> +      ));
> +      //
> +      // create a primary root port list if that port is connected
> +      //
> +      if (!IsListEmpty (&Device->ChildList)) {
> +        DEBUG ((
> +            DEBUG_INFO, "- has downstream device!\n"
> +        ));
> +        Status = AddPrimaryRootPortNode (Device, NumberOfRootPorts);
> +        if (EFI_ERROR (Status)) {
> +          DEBUG ((
> +              DEBUG_ERROR, "PCI configuration table allocation failure for #%d
> ::Bridge [%02x|%02x|%02x]\n",
> +              NumberOfRootPorts, Device->BusNumber, Device->DeviceNumber,
> Device->FunctionNumber
> +          ));
> +        }
> +      } else {
> +        DEBUG ((
> +            DEBUG_INFO, "- no downstream device!\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 ();
> +    }
> +  }
> +
> +  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
> index d06a5e8..b06c140 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> @@ -23,4 +23,150 @@ SPDX-License-Identifier: BSD-2-Clause-Patent  #define
> PCI_FEATURE_SUPPORT_FLAG_CCC  BIT13  #define
> PCI_FEATURE_SUPPORT_FLAG_ESYN BIT14  #define
> PCI_FEATURE_SUPPORT_FLAG_PTM  BIT20
> +
> +//
> +// 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;
> +  //
> +  // pointer to PCI_IO_DEVICE of the primary PCI Controller device
> +  //
> +  EFI_DEVICE_PATH_PROTOCOL                  *RootPortDevicePath;
> +  //
> +  // pointer to the corresponding PCI feature configuration Table node
> +  // all the child PCI devices of the controller are aligned based on
> +this table
> +  //
> +  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;
> +};
> +
> +
> +//
> +// 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;
> +
> +
> +/**
> +  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
> --
> 2.21.0.windows.1
> 
> 
> 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 06/12] PciBusDxe: Integration of setup for PCI feature enumeration
       [not found] ` <15D3127BE430E7DA.31784@groups.io>
@ 2019-11-13  3:28   ` Javeed, Ashraf
  2019-12-17 11:59     ` Ni, Ray
  0 siblings, 1 reply; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-13  3:28 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch is also uploaded in the following Repo, for review:-
https://github.com/ashrafj/edk2-staging/commit/9e42cc3c6e100c46a65f6e5926686d5f4d9fa58a

thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Friday, November 1, 2019 8:40 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 06/12]
> PciBusDxe: Integration of setup for PCI feature enumeration
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> 
> The code changes are made to integrate the setup infrastructure for the PCI
> feature enumeration, in the last phase of the PCI Bus driver, after its registration
> and its option ROM loading phase is complete.
> 
> Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> ---
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c  | 11 +++++++++++
> MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c | 15 ++++++++++++++-
> MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h | 11 +++++++++++
>  3 files changed, 36 insertions(+), 1 deletion(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> index 33a0e94..b839102 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> @@ -8,6 +8,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent  **/
> 
>  #include "PciBus.h"
> +#include "PciFeatureSupport.h"
> 
>  //
>  // This device structure is serviced as a header.
> @@ -170,6 +171,8 @@ DestroyRootBridgeByHandle (
> 
>      if (Temp->Handle == Controller) {
> 
> +      DestroyRootBridgePciFeaturesConfigCompletionList (Temp);
> +
>        RemoveEntryList (CurrentLink);
> 
>        DestroyPciDeviceTree (Temp);
> @@ -818,6 +821,14 @@ StartPciDevicesOnBridge (
>    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
>      //
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> index ab0e096..9e6671d 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> @@ -25,6 +25,19 @@ PRIMARY_ROOT_PORT_NODE
> *mPrimaryRootPortList;
>  **/
>  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 @@ -699,7 +712,7 @@ ProgramDevicePciFeatures (
>    IN PCI_IO_DEVICE          *PciDevice
>    )
>  {
> -  EFI_STATUS           Status;
> +  EFI_STATUS           Status = EFI_SUCCESS;
> 
>    return Status;
>  }
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> index b06c140..f92d008 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> @@ -138,6 +138,17 @@ typedef enum {
>  }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.
> --
> 2.21.0.windows.1
> 
> 
> 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] PciBusDxe: Record the PCI-Express Capability Structure
       [not found] ` <15D3127C6DFCD4A7.12315@groups.io>
@ 2019-11-13  3:29   ` Javeed, Ashraf
  2019-12-17 12:03     ` Ni, Ray
  0 siblings, 1 reply; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-13  3:29 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch is also uploaded in the following Repo, for review:-
https://github.com/ashrafj/edk2-staging/commit/8b40bc5cf23c57ad468939b84449a87c9d90b90a

thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Friday, November 1, 2019 8:40 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12]
> PciBusDxe: Record the PCI-Express Capability Structure
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> 
> The code changes are made to record the PCI device's PCI-Express Capability
> Structure register set during early PCI enumeration phase.
> This data shall be used during PCI feature enumeration phase.
> 
> Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> ---
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h               |  6 +++++-
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c | 34
> ++++++++++++++++++++++------------
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c    | 51
> +++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 78 insertions(+), 13 deletions(-)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> index 95a677b..dc29ef3 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> @@ -266,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;
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> index c7eafff..2343702 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
> index 9e6671d..df9e696 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> @@ -467,6 +467,14 @@ GetPciFeaturesConfigurationTable (
>      return EFI_SUCCESS;
>    }
> 
> +  //
> +  // 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;
> +  }
> 
>    if (IsDevicePathEnd (PciDevice->DevicePath)){
>      //
> @@ -575,6 +583,45 @@ IsPciRootPortEmpty (  }
> 
> 
> +/**
> +  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.
> 
> @@ -590,8 +637,12 @@ SetupDevicePciFeatures (
>    )
>  {
>    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)) {
> --
> 2.21.0.windows.1
> 
> 
> 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12] PciBusDxe: New PCI feature Max_Payload_Size
       [not found] ` <15D3127D273722D4.32624@groups.io>
@ 2019-11-13  3:30   ` Javeed, Ashraf
  2019-12-18  8:38     ` Ni, Ray
  0 siblings, 1 reply; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-13  3:30 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch is also uploaded in the following Repo for review:-
https://github.com/ashrafj/edk2-staging/commit/283733b638f1063ed3d37a6d79510f30a334c3ac

Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Friday, November 1, 2019 8:40 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12]
> PciBusDxe: New PCI feature Max_Payload_Size
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> 
> The code changes are made to enable the configuration of new PCI feature
> Max_Payload_Size (MPS), which defines the data packet size for the PCI
> transactions, as per the PCI Base Specification 4 Revision 1.
> 
> The code changes are made to calibrate highest common value that is appl-
> icable to all the child nodes originating from the primary parent root port of the
> root bridge instance.
> 
> This programming of MPS is based on each PCI device's capability, and also its
> device-specific platform policy obtained using the new PCI Platform Protocol
> interface, 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.h             |   4 ++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  | 157
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h  |   5 +++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c |  59
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h |  32
> ++++++++++++++++++++++++++++++++
>  5 files changed, 257 insertions(+)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> index dc29ef3..065ae54 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> @@ -286,6 +286,10 @@ struct _PCI_IO_DEVICE {
>    // This field is used to support this case.
>    //
>    UINT16                                    BridgeIoAlignment;
> +  //
> +  // Other PCI features setup flags
> +  //
> +  UINT8                                     SetupMPS;
>  };
> 
>  #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ diff --git
> a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> index df9e696..8fdaa05 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> @@ -582,6 +582,146 @@ IsPciRootPortEmpty (
>    return FALSE;
>  }
> 
> +/**
> +  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;
> +        }
> +      }
> +    } 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) {
> +      PciFeaturesConfigurationTable->Max_Payload_Size = MpsValue;
> +    }
> +  }
> +
> +  DEBUG (( DEBUG_INFO,
> +      "MPS: %d [DevCap:%d],",
> +      PciDevice->SetupMPS, PciDeviceCap.Bits.MaxPayloadSize
> +  ));
> +  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;
> +  EFI_TPL                     OldTpl;
> +
> +  PcieDev.Uint16 = 0;
> +  Offset = PciDevice->PciExpressCapabilityOffset +
> +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> + Status = PciDevice->PciIo.Pci.Read (
> +                                  &PciDevice->PciIo,
> +                                  EfiPciIoWidthUint16,
> +                                  Offset,
> +                                  1,
> +                                  &PcieDev.Uint16
> +                                );
> +  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, "MPS=%d,", PciDevice->SetupMPS));
> +
> +    //
> +    // Raise TPL to high level to disable timer interrupt while the write operation
> completes
> +    //
> +    OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
> +
> +    Status = PciDevice->PciIo.Pci.Write (
> +                                    &PciDevice->PciIo,
> +                                    EfiPciIoWidthUint16,
> +                                    Offset,
> +                                    1,
> +                                    &PcieDev.Uint16
> +                                  );
> +    //
> +    // Restore TPL to its original level
> +    //
> +    gBS->RestoreTPL (OldTpl);
> +
> +    if (!EFI_ERROR(Status)) {
> +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> +    } else {
> +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) write
> error!",
> +          Offset
> +      ));
> +    }
> +  } else {
> +    DEBUG (( DEBUG_INFO, "No write of MPS=%d,", PciDevice->SetupMPS));
> + }
> +
> +  return Status;
> +}
> 
>  /**
>    helper routine to dump the PCIe Device Port Type @@ -669,6 +809,18 @@
> SetupDevicePciFeatures (
>      }
>    }
> 
> +  DEBUG ((DEBUG_INFO, "["));
> +  //
> +  // process the PCI device Max_Payload_Size feature  //  if
> + (SetupMaxPayloadSize ()) {
> +    Status = ProcessMaxPayloadSize (
> +              PciDevice,
> +              PciConfigPhase,
> +              OtherPciFeaturesConfigTable
> +              );
> +  }
> +  DEBUG ((DEBUG_INFO, "]\n"));
>    return Status;
>  }
> 
> @@ -765,6 +917,10 @@ ProgramDevicePciFeatures (  {
>    EFI_STATUS           Status = EFI_SUCCESS;
> 
> +  if (SetupMaxPayloadSize ()) {
> +    Status = OverrideMaxPayloadSize (PciDevice);  }  DEBUG ((
> + DEBUG_INFO, "\n"));
>    return Status;
>  }
> 
> @@ -878,6 +1034,7 @@ AddPrimaryRootPortNode (
>                      );
>    if (PciConfigTable) {
>      PciConfigTable->ID                          = PortNumber;
> +    PciConfigTable->Max_Payload_Size            =
> PCIE_MAX_PAYLOAD_SIZE_4096B;
>    }
>    RootPortNode->OtherPciFeaturesConfigurationTable  = PciConfigTable;
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> index f92d008..e5ac2a3 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> @@ -79,6 +79,11 @@ 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;
>  };
> 
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> index 238959e..99badd6 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> @@ -356,6 +356,63 @@ GetPlatformPciOptionRom (
>    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;
> +  }
> +}
> +
> +/**
> +  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;
> +  }
> +}
> +
>  /**
>    Generic routine to setup the PCI features as per its predetermined defaults.
>  **/
> @@ -364,6 +421,7 @@ SetupDefaultsDevicePlatformPolicy (
>    IN  PCI_IO_DEVICE               *PciDevice
>    )
>  {
> +  PciDevice->SetupMPS = EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO;
>  }
> 
>  /**
> @@ -399,6 +457,7 @@ GetPciDevicePlatformPolicyEx (
>        //
>        // platform chipset policies are returned for this PCI device
>        //
> +      PciIoDevice->SetupMPS = PciPlatformExtendedPolicy.DeviceCtlMPS;
> 
>        DEBUG ((
>            DEBUG_INFO, "[device policy: platform]"
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> index a13131c..786c00d 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> @@ -124,4 +124,36 @@ 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
> +);
> +
> +/**
> +  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
> +);
>  #endif
> --
> 2.21.0.windows.1
> 
> 
> 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 09/12] PciBusDxe: New PCI feature Max_Read_Req_Size
       [not found] ` <15D3127DA6E2D860.7420@groups.io>
@ 2019-11-13  3:31   ` Javeed, Ashraf
  0 siblings, 0 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-13  3:31 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch is also uploaded in the following Repo for review:-
https://github.com/ashrafj/edk2-staging/commit/d16d7ea7df972fb711bca22266743c3602cf450b

Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Friday, November 1, 2019 8:40 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 09/12]
> PciBusDxe: New PCI feature Max_Read_Req_Size
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> 
> The code changes are made to enable the configuration of new PCI feature
> Max_Read_Req_Size (MRRS), which defines the memory read request size for
> the PCI transactions, as per the PCI Base Specification 4 Revision 1.
> 
> The code changes are made to configure a common value that is applicable to
> all the child nodes originating from the primary parent root port of the root
> bridge instance, based on following 3 criteria:-
> (1) if platform defines MRRS device policy for any one PCI device in the
>      tree than align all the devices in the PCI tree to that same value
> (2) if platform does not provide device policy for any of the devices in
>     the PCI tree than setup the MRRS value equivalent to MPS value for
>     all PCI devices to meet the criteria for the isochronous traffic
> (3) if platform does not provide device policy for any of the devices in
>     the PCI tree and platform firmware policy has not selected the PCI
>     bus driver to configure the MPS; than configuration of the MRRS is
>     performed based on highest common value of the MPS advertized in the
>     PCI device capability registers of the PCI devices
> 
> This programming of MRRS gets the device-specific platform policy using the
> new PCI Platform Protocol interface, 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.h             |   1 +
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  | 204
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h  |   9 +++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c |  59
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h |  32
> ++++++++++++++++++++++++++++++++
>  5 files changed, 305 insertions(+)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> index 065ae54..38abd20 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> @@ -290,6 +290,7 @@ struct _PCI_IO_DEVICE {
>    // 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/PciFeatureSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> index 8fdaa05..614285f 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> @@ -650,6 +650,121 @@ ProcessMaxPayloadSize (
>    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, "MRRS: %d,", PciDevice->SetupMRRS));
> +
> +  return EFI_SUCCESS;
> +}
> +
>  /**
>    Overrides the PCI Device Control register MaxPayloadSize register field; if
>    the hardware value is different than the intended value.
> @@ -723,6 +838,79 @@ OverrideMaxPayloadSize (
>    return Status;
>  }
> 
> +/**
> +  Overrides the PCI Device Control register Max_Read_Req_Size register
> +field; if
> +  the hardware value is different than the intended value.
> +
> +  @param  PciDevice             A pointer to the PCI_IO_DEVICE instance.
> +
> +  @retval EFI_SUCCESS           The data was read from or written to the PCI
> controller.
> +  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width,
> and Count is not
> +                                valid for the PCI configuration header of the PCI controller.
> +  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
> +
> +**/
> +EFI_STATUS
> +OverrideMaxReadReqSize (
> +  IN PCI_IO_DEVICE          *PciDevice
> +  )
> +{
> +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> +  UINT32                      Offset;
> +  EFI_STATUS                  Status;
> +  EFI_TPL                     OldTpl;
> +
> +  PcieDev.Uint16 = 0;
> +  Offset = PciDevice->PciExpressCapabilityOffset +
> +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> + Status = PciDevice->PciIo.Pci.Read (
> +                                  &PciDevice->PciIo,
> +                                  EfiPciIoWidthUint16,
> +                                  Offset,
> +                                  1,
> +                                  &PcieDev.Uint16
> +                                );
> +  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,",
> + PciDevice->SetupMRRS));
> +
> +    //
> +    // Raise TPL to high level to disable timer interrupt while the write operation
> completes
> +    //
> +    OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
> +
> +    Status = PciDevice->PciIo.Pci.Write (
> +                                    &PciDevice->PciIo,
> +                                    EfiPciIoWidthUint16,
> +                                    Offset,
> +                                    1,
> +                                    &PcieDev.Uint16
> +                                  );
> +    //
> +    // Restore TPL to its original level
> +    //
> +    gBS->RestoreTPL (OldTpl);
> +
> +    if (!EFI_ERROR(Status)) {
> +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> +    } else {
> +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) write
> error!",
> +          Offset
> +      ));
> +    }
> +  } else {
> +    DEBUG (( DEBUG_INFO, "No write of MRRS=%d,",
> + PciDevice->SetupMRRS));  }
> +
> +  return Status;
> +}
> +
>  /**
>    helper routine to dump the PCIe Device Port Type  **/ @@ -820,6 +1008,17
> @@ SetupDevicePciFeatures (
>                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
> +              );
> +  }
>    DEBUG ((DEBUG_INFO, "]\n"));
>    return Status;
>  }
> @@ -920,6 +1119,9 @@ ProgramDevicePciFeatures (
>    if (SetupMaxPayloadSize ()) {
>      Status = OverrideMaxPayloadSize (PciDevice);
>    }
> +  if (SetupMaxReadReqSize ()) {
> +    Status = OverrideMaxReadReqSize (PciDevice);  }
>    DEBUG (( DEBUG_INFO, "\n"));
>    return Status;
>  }
> @@ -1035,6 +1237,8 @@ AddPrimaryRootPortNode (
>    if (PciConfigTable) {
>      PciConfigTable->ID                          = PortNumber;
>      PciConfigTable->Max_Payload_Size            =
> PCIE_MAX_PAYLOAD_SIZE_4096B;
> +    PciConfigTable->Max_Read_Request_Size       =
> PCIE_MAX_READ_REQ_SIZE_4096B;
> +    PciConfigTable->Lock_Max_Read_Request_Size  = FALSE;
>    }
>    RootPortNode->OtherPciFeaturesConfigurationTable  = PciConfigTable;
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> index e5ac2a3..96ee6ff 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> @@ -84,6 +84,15 @@ struct _OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> {
>    // size among all the PCI devices in the PCI hierarchy
>    //
>    UINT8                                     Max_Payload_Size;
> +  //
> +  // to configure the PCI feature maximum read request size to maintain
> + the memory  // requester size among all the PCI devices in the PCI
> + hierarchy  //
> +  UINT8                                     Max_Read_Request_Size;
> +  //
> +  // lock the Max_Read_Request_Size for the entire PCI tree of a root
> + port  //
> +  BOOLEAN                                   Lock_Max_Read_Request_Size;
>  };
> 
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> index 99badd6..f032b5d 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> @@ -379,6 +379,29 @@ SetupMpsAsPerDeviceCapability (
>    }
>  }
> 
> +/**
> +  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 @@ -413,6 +436,40 @@ TranslateMpsSetupValueToPci (
>    }
>  }
> 
> +/**
> +  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.
>  **/
> @@ -422,6 +479,7 @@ SetupDefaultsDevicePlatformPolicy (
>    )
>  {
>    PciDevice->SetupMPS = EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO;
> +  PciDevice->SetupMRRS = EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO;
>  }
> 
>  /**
> @@ -458,6 +516,7 @@ GetPciDevicePlatformPolicyEx (
>        // platform chipset policies are returned for this PCI device
>        //
>        PciIoDevice->SetupMPS = PciPlatformExtendedPolicy.DeviceCtlMPS;
> +      PciIoDevice->SetupMRRS = PciPlatformExtendedPolicy.DeviceCtlMRRS;
> 
>        DEBUG ((
>            DEBUG_INFO, "[device policy: platform]"
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> index 786c00d..8ed3836 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> @@ -141,6 +141,22 @@ 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 @@ -156,4 +172,20 @@ 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
> --
> 2.21.0.windows.1
> 
> 
> 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 10/12] PciBusDxe: New PCI feature Relax Ordering
       [not found] ` <15D3127E471DF360.32624@groups.io>
@ 2019-11-13  3:32   ` Javeed, Ashraf
  0 siblings, 0 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-13  3:32 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch is also uploaded in the following Repo for review:-
https://github.com/ashrafj/edk2-staging/commit/8575d730644eda27a4b88888b0eb05ee1f804b35

Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Friday, November 1, 2019 8:40 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 10/12]
> PciBusDxe: New PCI feature Relax Ordering
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2313
> 
> The code changes are made to enable the configuration of new PCI feature
> Relax Ordering (OR), which enables the PCI function to initiate requests if it does
> not require strong write ordering for its transactions; as per the PCI Base
> Specification 4 Revision 1.
> 
> The code changes are made to configure only those PCI devices which are
> requested to override by platform through the new PCI Platform protocol
> interface for device-specific policies.
> 
> Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> ---
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h             |  2 ++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  | 78
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h  | 26
> ++++++++++++++++++++++++++
> MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 44
> ++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 150 insertions(+)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> index 38abd20..9f017b7 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> @@ -82,6 +82,7 @@ typedef enum {
>  #include "PciHotPlugSupport.h"
>  #include "PciLib.h"
>  #include "PciPlatformSupport.h"
> +#include "PciFeatureSupport.h"
> 
>  #define VGABASE1  0x3B0
>  #define VGALIMIT1 0x3BB
> @@ -291,6 +292,7 @@ struct _PCI_IO_DEVICE {
>    //
>    UINT8                                     SetupMPS;
>    UINT8                                     SetupMRRS;
> +  PCI_FEATURE_POLICY                        SetupRO;
>  };
> 
>  #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ diff --git
> a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> index 614285f..a60cb42 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> @@ -911,6 +911,81 @@ OverrideMaxReadReqSize (
>    return Status;
>  }
> 
> +/**
> +  Overrides the PCI Device Control register Relax Order register field;
> +if
> +  the hardware value is different than the intended value.
> +
> +  @param  PciDevice             A pointer to the PCI_IO_DEVICE instance.
> +
> +  @retval EFI_SUCCESS           The data was read from or written to the PCI
> device.
> +  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width,
> and Count is not
> +                                valid for the PCI configuration header of the PCI controller.
> +  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
> +
> +**/
> +EFI_STATUS
> +OverrideRelaxOrder (
> +  IN PCI_IO_DEVICE          *PciDevice
> +  )
> +{
> +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> +  UINT32                      Offset;
> +  EFI_STATUS                  Status;
> +  EFI_TPL                     OldTpl;
> +
> +  PcieDev.Uint16 = 0;
> +  Offset = PciDevice->PciExpressCapabilityOffset +
> +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> + Status = PciDevice->PciIo.Pci.Read (
> +                                  &PciDevice->PciIo,
> +                                  EfiPciIoWidthUint16,
> +                                  Offset,
> +                                  1,
> +                                  &PcieDev.Uint16
> +                                );
> +  if (EFI_ERROR(Status)){
> +    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) read
> error!",
> +        Offset
> +    ));
> +    return Status;
> +  }
> +  if (PciDevice->SetupRO.Override
> +      &&  PcieDev.Bits.RelaxedOrdering != PciDevice->SetupRO.Act
> +      ) {
> +    PcieDev.Bits.RelaxedOrdering = PciDevice->SetupRO.Act;
> +    DEBUG (( DEBUG_INFO, "RO=%d,", PciDevice->SetupRO.Act));
> +
> +    //
> +    // Raise TPL to high level to disable timer interrupt while the write operation
> completes
> +    //
> +    OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
> +
> +    Status = PciDevice->PciIo.Pci.Write (
> +                                    &PciDevice->PciIo,
> +                                    EfiPciIoWidthUint16,
> +                                    Offset,
> +                                    1,
> +                                    &PcieDev.Uint16
> +                                  );
> +    //
> +    // Restore TPL to its original level
> +    //
> +    gBS->RestoreTPL (OldTpl);
> +
> +    if (!EFI_ERROR(Status)) {
> +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> +    } else {
> +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) write
> error!",
> +          Offset
> +      ));
> +    }
> +  } else {
> +    DEBUG (( DEBUG_INFO, "No write of RO,", PciDevice->SetupRO.Act));
> + }
> +
> +  return Status;
> +}
> +
>  /**
>    helper routine to dump the PCIe Device Port Type  **/ @@ -1122,6 +1197,9
> @@ ProgramDevicePciFeatures (
>    if (SetupMaxReadReqSize ()) {
>      Status = OverrideMaxReadReqSize (PciDevice);
>    }
> +  if (SetupRelaxOrder ()) {
> +    Status = OverrideRelaxOrder (PciDevice);  }
>    DEBUG (( DEBUG_INFO, "\n"));
>    return Status;
>  }
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> index 96ee6ff..5044dc2 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> @@ -40,6 +40,11 @@ typedef struct
> _OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> OTHER_PCI_FEATURES_CONFI  //  typedef struct
> _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> PCI_FEATURE_CONFIGURATION_COMPLETION_LIST;
> 
> +//
> +// define the data type for the PCI feature policy support // typedef
> +struct _PCI_FEATURE_POLICY  PCI_FEATURE_POLICY;
> +
>  //
>  // Signature value for the PCI Root Port node  // @@ -151,6 +156,27 @@
> typedef enum {
> 
>  }PCI_FEATURE_CONFIGURATION_PHASE;
> 
> +//
> +// declaration for the data type to harbor the PCI feature policies //
> +struct  _PCI_FEATURE_POLICY {
> +  //
> +  // if set, it indicates the feature should be enabled
> +  // if clear, it indicates the feature should be disabled
> +  //
> +  UINT8   Act : 1;
> +  //
> +  // this field will be specific to feature, it can be implementation
> +specific
> +  // or it can be reserved and remain unused
> +  //
> +  UINT8   Support : 6;
> +  //
> +  // if set indicates override the feature policy defined by the
> +members above
> +  // if clear it indicates that this feature policy should be ignored
> +completely
> +  // this means the above two members should not be used
> +  //
> +  UINT8   Override : 1;
> +};
> 
>  /**
>    Main routine to indicate platform selection of any of the other PCI features
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> index f032b5d..f1e7039 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> @@ -470,6 +470,45 @@ TranslateMrrsSetupValueToPci (
>    }
>  }
> 
> +/**
> +  Routine to set the device-specific policy for the PCI feature Relax
> +Ordering
> +
> +  @param  RelaxOrder    value corresponding to data type
> EFI_PCI_CONF_RELAX_ORDER
> +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> +**/
> +VOID
> +SetDevicePolicyRelaxOrder (
> +  IN  EFI_PCI_CONF_RELAX_ORDER    RelaxOrder,
> +  OUT PCI_IO_DEVICE               *PciDevice
> +  )
> +{
> +  //
> +  // implementation specific rules for the usage of PCI_FEATURE_POLICY
> +members
> +  // exclusively for the PCI Feature Relax Ordering (RO)
> +  //
> +  // .Override = 0 to skip this PCI feature RO for the PCI device
> +  // .Override = 1 to program this RO PCI feature
> +  //      .Act = 1 to enable the RO in the PCI device
> +  //      .Act = 0 to disable the RO in the PCI device
> +  //
> +  switch (RelaxOrder) {
> +    case  EFI_PCI_CONF_RO_AUTO:
> +      PciDevice->SetupRO.Override = 0;
> +      break;
> +    case  EFI_PCI_CONF_RO_DISABLE:
> +      PciDevice->SetupRO.Override = 1;
> +      PciDevice->SetupRO.Act = 0;
> +      break;
> +    case  EFI_PCI_CONF_RO_ENABLE:
> +      PciDevice->SetupRO.Override = 1;
> +      PciDevice->SetupRO.Act = 1;
> +      break;
> +    default:
> +      PciDevice->SetupRO.Override = 0;
> +      break;
> +  }
> +}
> +
>  /**
>    Generic routine to setup the PCI features as per its predetermined defaults.
>  **/
> @@ -480,6 +519,7 @@ SetupDefaultsDevicePlatformPolicy (  {
>    PciDevice->SetupMPS = EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO;
>    PciDevice->SetupMRRS = EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO;
> +  PciDevice->SetupRO.Override = 0;
>  }
> 
>  /**
> @@ -517,6 +557,10 @@ GetPciDevicePlatformPolicyEx (
>        //
>        PciIoDevice->SetupMPS = PciPlatformExtendedPolicy.DeviceCtlMPS;
>        PciIoDevice->SetupMRRS = PciPlatformExtendedPolicy.DeviceCtlMRRS;
> +      //
> +      // set device specific policy for Relax Ordering
> +      //
> +      SetDevicePolicyRelaxOrder
> + (PciPlatformExtendedPolicy.DeviceCtlRelaxOrder, PciIoDevice);
> 
>        DEBUG ((
>            DEBUG_INFO, "[device policy: platform]"
> --
> 2.21.0.windows.1
> 
> 
> 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 11/12] PciBusDxe: New PCI feature No-Snoop
       [not found] ` <15D3127EB6ED8506.12315@groups.io>
@ 2019-11-13  3:33   ` Javeed, Ashraf
  0 siblings, 0 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-13  3:33 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch is also uploaded in following Repo for review:-
https://github.com/ashrafj/edk2-staging/commit/da0d50ad3b542fc4b63f8debb7d690c83ef4218d

Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Friday, November 1, 2019 8:40 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 11/12]
> PciBusDxe: New PCI feature No-Snoop
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2313
> 
> The code changes are made; as per the PCI Base Specification 4 Revision 1; to
> enable the configuration of new PCI feature No-Snoop (NS), which enables the
> PCI function to initiate requests if it does not require har- dware enforced
> cache-coherency for its transactions.
> 
> The code changes are made to configure only those PCI devices which are
> requested to override by platform through the new PCI Platform protocol
> interface for device-specific policies.
> 
> Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> ---
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h             |  1 +
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  | 78
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 45
> +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 124 insertions(+)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> index 9f017b7..be1c341 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> @@ -293,6 +293,7 @@ struct _PCI_IO_DEVICE {
>    UINT8                                     SetupMPS;
>    UINT8                                     SetupMRRS;
>    PCI_FEATURE_POLICY                        SetupRO;
> +  PCI_FEATURE_POLICY                        SetupNS;
>  };
> 
>  #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ diff --git
> a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> index a60cb42..a7f0a2f 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> @@ -986,6 +986,81 @@ OverrideRelaxOrder (
>    return Status;
>  }
> 
> +/**
> +  Overrides the PCI Device Control register No-Snoop register field; if
> +  the hardware value is different than the intended value.
> +
> +  @param  PciDevice             A pointer to the PCI_IO_DEVICE instance.
> +
> +  @retval EFI_SUCCESS           The data was read from or written to the PCI
> device.
> +  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width,
> and Count is not
> +                                valid for the PCI configuration header of the PCI controller.
> +  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
> +
> +**/
> +EFI_STATUS
> +OverrideNoSnoop (
> +  IN PCI_IO_DEVICE          *PciDevice
> +  )
> +{
> +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> +  UINT32                      Offset;
> +  EFI_STATUS                  Status;
> +  EFI_TPL                     OldTpl;
> +
> +  PcieDev.Uint16 = 0;
> +  Offset = PciDevice->PciExpressCapabilityOffset +
> +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> + Status = PciDevice->PciIo.Pci.Read (
> +                                  &PciDevice->PciIo,
> +                                  EfiPciIoWidthUint16,
> +                                  Offset,
> +                                  1,
> +                                  &PcieDev.Uint16
> +                                );
> +  if (EFI_ERROR(Status)){
> +    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) read
> error!",
> +        Offset
> +    ));
> +    return Status;
> +  }
> +  if (PciDevice->SetupRO.Override
> +      &&  PcieDev.Bits.NoSnoop != PciDevice->SetupNS.Act
> +      ) {
> +    PcieDev.Bits.NoSnoop = PciDevice->SetupNS.Act;
> +    DEBUG (( DEBUG_INFO, "NS=%d", PciDevice->SetupNS.Act));
> +
> +    //
> +    // Raise TPL to high level to disable timer interrupt while the write operation
> completes
> +    //
> +    OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
> +
> +    Status = PciDevice->PciIo.Pci.Write (
> +                                    &PciDevice->PciIo,
> +                                    EfiPciIoWidthUint16,
> +                                    Offset,
> +                                    1,
> +                                    &PcieDev.Uint16
> +                                  );
> +    //
> +    // Restore TPL to its original level
> +    //
> +    gBS->RestoreTPL (OldTpl);
> +
> +    if (!EFI_ERROR(Status)) {
> +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> +    } else {
> +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) write
> error!",
> +          Offset
> +      ));
> +    }
> +  } else {
> +    DEBUG (( DEBUG_INFO, "No write of NS,", PciDevice->SetupRO.Act));
> + }
> +
> +  return Status;
> +}
> +
>  /**
>    helper routine to dump the PCIe Device Port Type  **/ @@ -1200,6 +1275,9
> @@ ProgramDevicePciFeatures (
>    if (SetupRelaxOrder ()) {
>      Status = OverrideRelaxOrder (PciDevice);
>    }
> +  if (SetupNoSnoop ()) {
> +    Status = OverrideNoSnoop (PciDevice);  }
>    DEBUG (( DEBUG_INFO, "\n"));
>    return Status;
>  }
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> index f1e7039..47295cd 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> @@ -509,6 +509,46 @@ SetDevicePolicyRelaxOrder (
>    }
>  }
> 
> +/**
> +  Routine to set the device-specific policy for the PCI feature
> +No-Snoop enable
> +  or disable
> +
> +  @param  NoSnoop       value corresponding to data type
> EFI_PCI_CONF_NO_SNOOP
> +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> +**/
> +VOID
> +SetDevicePolicyNoSnoop (
> +  IN  EFI_PCI_CONF_NO_SNOOP       NoSnoop,
> +  OUT PCI_IO_DEVICE               *PciDevice
> +  )
> +{
> +  //
> +  // implementation specific rules for the usage of PCI_FEATURE_POLICY
> +members
> +  // exclusively for the PCI Feature No-Snoop
> +  //
> +  // .Override = 0 to skip this PCI feature No-Snoop for the PCI device
> +  // .Override = 1 to program this No-Snoop PCI feature
> +  //      .Act = 1 to enable the No-Snoop in the PCI device
> +  //      .Act = 0 to disable the No-Snoop in the PCI device
> +  //
> +  switch (NoSnoop) {
> +    case  EFI_PCI_CONF_NS_AUTO:
> +      PciDevice->SetupNS.Override = 0;
> +      break;
> +    case  EFI_PCI_CONF_NS_DISABLE:
> +      PciDevice->SetupNS.Override = 1;
> +      PciDevice->SetupNS.Act = 0;
> +      break;
> +    case  EFI_PCI_CONF_NS_ENABLE:
> +      PciDevice->SetupNS.Override = 1;
> +      PciDevice->SetupNS.Act = 1;
> +      break;
> +    default:
> +      PciDevice->SetupNS.Override = 0;
> +      break;
> +  }
> +}
> +
>  /**
>    Generic routine to setup the PCI features as per its predetermined defaults.
>  **/
> @@ -520,6 +560,7 @@ SetupDefaultsDevicePlatformPolicy (
>    PciDevice->SetupMPS = EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO;
>    PciDevice->SetupMRRS = EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO;
>    PciDevice->SetupRO.Override = 0;
> +  PciDevice->SetupNS.Override = 0;
>  }
> 
>  /**
> @@ -561,6 +602,10 @@ GetPciDevicePlatformPolicyEx (
>        // set device specific policy for Relax Ordering
>        //
>        SetDevicePolicyRelaxOrder
> (PciPlatformExtendedPolicy.DeviceCtlRelaxOrder, PciIoDevice);
> +      //
> +      // set the device specific policy for No-Snoop
> +      //
> +      SetDevicePolicyNoSnoop
> + (PciPlatformExtendedPolicy.DeviceCtlNoSnoop, PciIoDevice);
> 
>        DEBUG ((
>            DEBUG_INFO, "[device policy: platform]"
> --
> 2.21.0.windows.1
> 
> 
> 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 12/12] PciBusDxe: New PCI feature Completion Timeout
       [not found] ` <15D3127F5541064B.31784@groups.io>
@ 2019-11-13  3:34   ` Javeed, Ashraf
  0 siblings, 0 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-11-13  3:34 UTC (permalink / raw)
  To: devel@edk2.groups.io, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A, Ni, Ray

This patch is also uploaded in the following Repo for review:-
https://github.com/ashrafj/edk2-staging/commit/fc451a1bb20fc774f7542ea06eb4e1b9ce369c0c

Thanks
Ashraf

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> Ashraf
> Sent: Friday, November 1, 2019 8:40 PM
> To: devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> Ni, Ray <ray.ni@intel.com>
> Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 12/12]
> PciBusDxe: New PCI feature Completion Timeout
> 
> BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2313
> 
> The code changes are made; as per the PCI Base Specification 4 Revision 1; to
> enable the configuration of new PCI feature Completion Timeout (CTO), which
> enables the PCI function to wait on programmed duration for its transactions
> before timeout, or disable its detection mechanism.
> 
> The code changes are made to configure only those PCI devices which are
> requested to override by platform through the new PCI Platform protocol
> interface for device-specific policies. The changes are made to also com- ply
> with the device-specific capability attributes.
> 
> The code follows the below implementation specific rules in case the req-
> uested platform policy does not match with the device-specific capability
> attributes:-
> (1) if device is capable of Range A only and if platform ask for any of
>     ranges B, C, D; than this implementation will only program the default
>     range value for the duration of 50us to 50ms
> (2) if device is capable of Range B, or range B & C, or Ranges B, C & D
>     only and if the platform ask for the Range A; than this implementation
>     will only program the default range value for the duration of 50us to
>     50ms
> (3) if the device is capable of Range B only, or the ranges A & B; and if
>     the platform ask for Range C, or Range D values, than this implement-
>     ation will only program the Range B value for the duration of 65ms to
>     210ms
> (4) if the device is capable of Ranges B & C, or Ranges A, B, and C; and
>     if the platform ask for Range D values; than this implementation will
>     only program the Range C for the duration of 1s to 3.5s
> 
> 
> Signed-off-by: Ashraf Javeed <ashraf.javeed@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Hao A Wu <hao.a.wu@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> ---
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h             |   1 +
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c  | 413
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++++++
>  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c |  84
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> +++++++++++++++++++
>  3 files changed, 498 insertions(+)
> 
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> index be1c341..b6ec14f 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> @@ -294,6 +294,7 @@ struct _PCI_IO_DEVICE {
>    UINT8                                     SetupMRRS;
>    PCI_FEATURE_POLICY                        SetupRO;
>    PCI_FEATURE_POLICY                        SetupNS;
> +  PCI_FEATURE_POLICY                        SetupCTO;
>  };
> 
>  #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ diff --git
> a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> index a7f0a2f..ba0de0d 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> @@ -765,6 +765,294 @@ ProcessMaxReadReqSize (
>    return EFI_SUCCESS;
>  }
> 
> +/**
> +  To determine the CTO Range A values
> +
> +  @param  CtoValue    input CTO range value from 0 to 14
> +  @retval TRUE        the given CTO value belongs to Range A
> +          FALSE       the given value does not belong to Range A
> +**/
> +BOOLEAN
> +IsCtoRangeA (
> +  IN  UINT8   CtoValue
> +  )
> +{
> +  switch (CtoValue) {
> +    case  PCIE_COMPLETION_TIMEOUT_50US_100US:
> +    case  PCIE_COMPLETION_TIMEOUT_1MS_10MS:
> +      return TRUE;
> +  }
> +  return FALSE;
> +}
> +
> +/**
> +  To determine the CTO Range B values
> +
> +  @param  CtoValue    input CTO range value from 0 to 14
> +  @retval TRUE        the given CTO value belongs to Range B
> +          FALSE       the given value does not belong to Range B
> +**/
> +BOOLEAN
> +IsCtoRangeB (
> +  IN  UINT8   CtoValue
> +  )
> +{
> +  switch (CtoValue) {
> +    case  PCIE_COMPLETION_TIMEOUT_16MS_55MS:
> +    case  PCIE_COMPLETION_TIMEOUT_65MS_210MS:
> +      return TRUE;
> +  }
> +  return FALSE;
> +}
> +
> +/**
> +  To determine the CTO Range C values
> +
> +  @param  CtoValue    input CTO range value from 0 to 14
> +  @retval TRUE        the given CTO value belongs to Range C
> +          FALSE       the given value does not belong to Range C
> +**/
> +BOOLEAN
> +IsCtoRangeC (
> +  IN  UINT8   CtoValue
> +  )
> +{
> +  switch (CtoValue) {
> +    case  PCIE_COMPLETION_TIMEOUT_260MS_900MS:
> +    case  PCIE_COMPLETION_TIMEOUT_1S_3_5S:
> +      return TRUE;
> +  }
> +  return FALSE;
> +}
> +
> +/**
> +  To determine the CTO Range D values
> +
> +  @param  CtoValue    input CTO range value from 0 to 14
> +  @retval TRUE        the given CTO value belongs to Range D
> +          FALSE       the given value does not belong to Range D
> +**/
> +BOOLEAN
> +IsCtoRangeD (
> +  IN  UINT8   CtoValue
> +  )
> +{
> +  switch (CtoValue) {
> +    case  PCIE_COMPLETION_TIMEOUT_4S_13S:
> +    case  PCIE_COMPLETION_TIMEOUT_17S_64S:
> +      return TRUE;
> +  }
> +  return FALSE;
> +}
> +
> +/**
> +  The main routine which process the PCI feature Completion Timeout as
> +per the
> +  device-specific platform policy, as well as in complaince with the
> +PCI Base
> +  specification Revision 4.
> +
> +  @param PciDevice                      A pointer to the PCI_IO_DEVICE.
> +  @param PciConfigPhase                 for the PCI feature configuration phases:
> +                                        PciFeatureGetDevicePolicy &
> + PciFeatureSetupPhase
> +
> +  @retval EFI_SUCCESS                   processing of PCI feature CTO is successful.
> +**/
> +EFI_STATUS
> +ProcessCompletionTimeout (
> +  IN  PCI_IO_DEVICE                           *PciDevice,
> +  IN  PCI_FEATURE_CONFIGURATION_PHASE         PciConfigPhase
> +  )
> +{
> +  PCI_REG_PCIE_DEVICE_CAPABILITY2 DeviceCap2;
> +  UINT8                           CtoRangeValue;
> +
> +  if (PciConfigPhase != PciFeatureGetDevicePolicy) {
> +    //
> +    // no reprocessing required for device CTO configuration
> +    //
> +    return  EFI_SUCCESS;
> +  }
> +
> +  if (!PciDevice->SetupCTO.Override) {
> +    //
> +    // No override of CTO is required for this device
> +    //
> +    return  EFI_SUCCESS;
> +  }
> +
> +  //
> +  // determine the CTO range values as per its device capability
> + register  //
> +  DeviceCap2.Uint32 = PciDevice->PciExpStruct.DeviceCapability2.Uint32;
> +  if (!DeviceCap2.Bits.CompletionTimeoutRanges
> +      && !DeviceCap2.Bits.CompletionTimeoutDisable
> +  ) {
> +    //
> +    // device does not support the CTO mechanism, hence no override is
> applicable
> +    //
> +    return EFI_SUCCESS;
> +  }
> +
> +  //
> +  // override the device CTO values if applicable  //  if
> + (PciDevice->SetupCTO.Act) {
> +    //
> +    // program the CTO range values
> +    //
> +    if (DeviceCap2.Bits.CompletionTimeoutRanges) {
> +      CtoRangeValue = PCIE_COMPLETION_TIMEOUT_50US_50MS;
> +      //
> +      // in case if the supported CTO range and the requirement from platform
> +      // policy does not match, than the CTO range setting would be based on
> +      // this driver's implementation specific, and its rules are as follows:-
> +      //
> +      // if device is capable of Range A only and if platform ask for any of
> +      // ranges B, C, D; than this implementation will only program the default
> +      // range value for the duration of 50us to 50ms.
> +      //
> +      // if device is capable of Range B, or range B & C, or Ranges B, C & D only
> +      // and if the platform ask for the Range A; than this implementation will
> +      // only program the default range value for the duration of 50us to 50ms.
> +      //
> +      // if the device is capable of Range B only, or the ranges A & B; and the
> +      // platform ask for Range C, or Range D values, than this implementation
> +      // will only program the Range B value for the duration of 65ms to 210ms.
> +      //
> +      // if the device is capable of Ranges B & C, or Ranges A, B, and C; and
> +      // if the platform ask for Range D values; than this implementation will
> +      // only program the Range C for the duration of 1s to 3.5s.
> +      //
> +
> +      switch (DeviceCap2.Bits.CompletionTimeoutRanges) {
> +        case  PCIE_COMPLETION_TIMEOUT_RANGE_A_SUPPORTED:
> +          if (IsCtoRangeA (PciDevice->SetupCTO.Support)) {
> +            CtoRangeValue = PciDevice->SetupCTO.Support;
> +          }
> +          //
> +          // if device is capable of Range A only and if platform ask for any of
> +          // ranges B, C, D; than this implementation will only program the default
> +          // range value for the duration of 50us to 50ms.
> +          //
> +          if (IsCtoRangeB (PciDevice->SetupCTO.Support)
> +              || IsCtoRangeC (PciDevice->SetupCTO.Support)
> +              || IsCtoRangeD (PciDevice->SetupCTO.Support)
> +          ) {
> +            CtoRangeValue = PCIE_COMPLETION_TIMEOUT_50US_50MS;
> +          }
> +          break;
> +
> +        case  PCIE_COMPLETION_TIMEOUT_RANGE_B_SUPPORTED:
> +          //
> +          // if device is capable of Range B, or range B & C, or Ranges B, C & D only
> +          // and if the platform ask for the Range A; than this implementation will
> +          // only program the default range value for the duration of 50us to 50ms.
> +          //
> +          if (IsCtoRangeA (PciDevice->SetupCTO.Support)) {
> +            CtoRangeValue = PCIE_COMPLETION_TIMEOUT_50US_50MS;
> +          }
> +
> +          if (IsCtoRangeB (PciDevice->SetupCTO.Support)) {
> +            CtoRangeValue = PciDevice->SetupCTO.Support;
> +          }
> +          //
> +          // if the device is capable of Range B only, or the ranges A & B; and the
> +          // platform ask for Range C, or Range D values, than this implementation
> +          // will only program the Range B value for the duration of 65ms to
> 210ms.
> +          //
> +          if (IsCtoRangeC (PciDevice->SetupCTO.Support)
> +              || IsCtoRangeD (PciDevice->SetupCTO.Support)
> +          ) {
> +            CtoRangeValue = PCIE_COMPLETION_TIMEOUT_65MS_210MS;
> +          }
> +          break;
> +
> +        case  PCIE_COMPLETION_TIMEOUT_RANGE_B_C_SUPPORTED:
> +          if (IsCtoRangeA (PciDevice->SetupCTO.Support)) {
> +            CtoRangeValue = PCIE_COMPLETION_TIMEOUT_50US_50MS;
> +          }
> +
> +          if (IsCtoRangeB (PciDevice->SetupCTO.Support)
> +              || IsCtoRangeC (PciDevice->SetupCTO.Support)
> +              ) {
> +            CtoRangeValue = PciDevice->SetupCTO.Support;
> +          }
> +          //
> +          // if the device is capable of Ranges B & C, or Ranges A, B, and C; and
> +          // if the platform ask for Range D values; than this implementation will
> +          // only program the Range C for the duration of 1s to 3.5s.
> +          //
> +          if (IsCtoRangeD (PciDevice->SetupCTO.Support)) {
> +            CtoRangeValue = PCIE_COMPLETION_TIMEOUT_1S_3_5S;
> +          }
> +          break;
> +
> +        case  PCIE_COMPLETION_TIMEOUT_RANGE_B_C_D_SUPPORTED:
> +          if (IsCtoRangeA (PciDevice->SetupCTO.Support)) {
> +            CtoRangeValue = PCIE_COMPLETION_TIMEOUT_50US_50MS;
> +          }
> +          if (IsCtoRangeB (PciDevice->SetupCTO.Support)
> +              || IsCtoRangeC (PciDevice->SetupCTO.Support)
> +              || IsCtoRangeD (PciDevice->SetupCTO.Support)
> +          ) {
> +            CtoRangeValue = PciDevice->SetupCTO.Support;
> +          }
> +          break;
> +
> +        case  PCIE_COMPLETION_TIMEOUT_RANGE_A_B_SUPPORTED:
> +          if (IsCtoRangeA (PciDevice->SetupCTO.Support)
> +              || IsCtoRangeB (PciDevice->SetupCTO.Support)
> +              ) {
> +            CtoRangeValue = PciDevice->SetupCTO.Support;
> +          }
> +          if (IsCtoRangeC (PciDevice->SetupCTO.Support)
> +              || IsCtoRangeD (PciDevice->SetupCTO.Support)
> +          ) {
> +            CtoRangeValue = PCIE_COMPLETION_TIMEOUT_65MS_210MS;
> +          }
> +          break;
> +
> +        case  PCIE_COMPLETION_TIMEOUT_RANGE_A_B_C_SUPPORTED:
> +          if (IsCtoRangeA (PciDevice->SetupCTO.Support)
> +              || IsCtoRangeB (PciDevice->SetupCTO.Support)
> +              || IsCtoRangeC (PciDevice->SetupCTO.Support)
> +          ) {
> +            CtoRangeValue = PciDevice->SetupCTO.Support;
> +          }
> +          if (IsCtoRangeD (PciDevice->SetupCTO.Support)) {
> +            CtoRangeValue = PCIE_COMPLETION_TIMEOUT_1S_3_5S;
> +          }
> +          break;
> +
> +        case  PCIE_COMPLETION_TIMEOUT_RANGE_A_B_C_D_SUPPORTED:
> +          if (IsCtoRangeA (PciDevice->SetupCTO.Support)
> +              || IsCtoRangeB (PciDevice->SetupCTO.Support)
> +              || IsCtoRangeC (PciDevice->SetupCTO.Support)
> +              || IsCtoRangeD (PciDevice->SetupCTO.Support)
> +          ) {
> +            CtoRangeValue = PciDevice->SetupCTO.Support;
> +          }
> +          break;
> +
> +        default:
> +          DEBUG ((
> +              DEBUG_ERROR, "Invalid CTO range: %d\n",
> +              DeviceCap2.Bits.CompletionTimeoutRanges
> +          ));
> +          return EFI_INVALID_PARAMETER;
> +      }
> +
> +      if (PciDevice->SetupCTO.Support != CtoRangeValue) {
> +        PciDevice->SetupCTO.Support = CtoRangeValue;
> +      }
> +    }
> +    DEBUG (( DEBUG_INFO, "CTO enable: %d, CTO range: 0x%x,",
> +        PciDevice->SetupCTO.Act,
> +        PciDevice->SetupCTO.Support
> +    ));
> +  }
> +  return EFI_SUCCESS;
> +}
> +
>  /**
>    Overrides the PCI Device Control register MaxPayloadSize register field; if
>    the hardware value is different than the intended value.
> @@ -1061,6 +1349,119 @@ OverrideNoSnoop (
>    return Status;
>  }
> 
> +/**
> +  Overrides the PCI Device Control2 register Completion Timeout range;
> +if
> +  the hardware value is different than the intended value.
> +
> +  @param  PciDevice             A pointer to the PCI_IO_DEVICE instance.
> +
> +  @retval EFI_SUCCESS           The data was read from or written to the PCI
> device.
> +  @retval EFI_UNSUPPORTED       The address range specified by Offset, Width,
> and Count is not
> +                                valid for the PCI configuration header of the PCI controller.
> +  @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid.
> +
> +**/
> +EFI_STATUS
> +OverrideCompletionTimeout (
> +  IN PCI_IO_DEVICE          *PciDevice
> +  )
> +{
> +  PCI_REG_PCIE_DEVICE_CONTROL2    DeviceCtl2;
> +  PCI_REG_PCIE_DEVICE_CAPABILITY2 DeviceCap2;
> +  UINT32                          Offset;
> +  EFI_STATUS                      Status;
> +  EFI_TPL                         OldTpl;
> +
> +  if (!PciDevice->SetupCTO.Override) {
> +    //
> +    // No override of CTO is required for this device
> +    //
> +    DEBUG (( DEBUG_INFO, "CTO skipped,"));
> +    return  EFI_SUCCESS;
> +  }
> +
> +  //
> +  // to program the CTO range values, determine in its device
> + capability register  //
> +  DeviceCap2.Uint32 = PciDevice->PciExpStruct.DeviceCapability2.Uint32;
> +  if (DeviceCap2.Bits.CompletionTimeoutRanges
> +      || DeviceCap2.Bits.CompletionTimeoutDisable) {
> +    //
> +    // device supports the CTO mechanism
> +    //
> +    DeviceCtl2.Uint16 = 0;
> +    Offset = PciDevice->PciExpressCapabilityOffset +
> +              OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2);
> +    Status = PciDevice->PciIo.Pci.Read (
> +                                  &PciDevice->PciIo,
> +                                  EfiPciIoWidthUint16,
> +                                  Offset,
> +                                  1,
> +                                  &DeviceCtl2.Uint16
> +                                  );
> +    if (EFI_ERROR(Status)){
> +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl2 register (0x%x) read
> error!",
> +                Offset
> +      ));
> +      return Status;
> +    }
> +  } else {
> +    //
> +    // device does not support the CTO mechanism, hence no override
> performed
> +    //
> +    DEBUG (( DEBUG_INFO, "CTO n/a,"));
> +    return EFI_SUCCESS;
> +  }
> +
> +  //
> +  // override the device CTO values if applicable  //  if
> + (PciDevice->SetupCTO.Act) {
> +    //
> +    // program the CTO range values
> +    //
> +    if (PciDevice->SetupCTO.Support !=
> DeviceCtl2.Bits.CompletionTimeoutValue) {
> +      DeviceCtl2.Bits.CompletionTimeoutValue = PciDevice->SetupCTO.Support;
> +    }
> +  } else {
> +    //
> +    // disable the CTO mechanism in device
> +    //
> +    DeviceCtl2.Bits.CompletionTimeoutValue = 0;
> +    DeviceCtl2.Bits.CompletionTimeoutDisable = 1;  }  DEBUG ((
> + DEBUG_INFO, "CTO disable: %d, CTO range: 0x%x,",
> +      DeviceCtl2.Bits.CompletionTimeoutDisable,
> +      DeviceCtl2.Bits.CompletionTimeoutValue
> +  ));
> +
> +  //
> +  // Raise TPL to high level to disable timer interrupt while the write
> + operation completes  //  OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
> +
> +  Status = PciDevice->PciIo.Pci.Write (
> +                                &PciDevice->PciIo,
> +                                EfiPciIoWidthUint16,
> +                                Offset,
> +                                1,
> +                                &DeviceCtl2.Uint16
> +                                );
> +  //
> +  // Restore TPL to its original level
> +  //
> +  gBS->RestoreTPL (OldTpl);
> +
> +  if (!EFI_ERROR(Status)) {
> +    PciDevice->PciExpStruct.DeviceControl2.Uint16 = DeviceCtl2.Uint16;
> +  } else {
> +    DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl2 register (0x%x) write
> error!",
> +        Offset
> +    ));
> +  }
> +  return Status;
> +}
> +
>  /**
>    helper routine to dump the PCIe Device Port Type  **/ @@ -1169,6 +1570,15
> @@ SetupDevicePciFeatures (
>                OtherPciFeaturesConfigTable
>                );
>    }
> +  //
> +  // process the PCI device CTO range values to be configured  //  if
> + (SetupCompletionTimeout ()) {
> +    Status = ProcessCompletionTimeout (
> +              PciDevice,
> +              PciConfigPhase
> +              );
> +  }
>    DEBUG ((DEBUG_INFO, "]\n"));
>    return Status;
>  }
> @@ -1278,6 +1688,9 @@ ProgramDevicePciFeatures (
>    if (SetupNoSnoop ()) {
>      Status = OverrideNoSnoop (PciDevice);
>    }
> +  if (SetupCompletionTimeout()) {
> +    Status = OverrideCompletionTimeout (PciDevice);  }
>    DEBUG (( DEBUG_INFO, "\n"));
>    return Status;
>  }
> diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> index 47295cd..7ee0d7d 100644
> --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> @@ -549,6 +549,85 @@ SetDevicePolicyNoSnoop (
>    }
>  }
> 
> +/**
> +  Routine to set the device-specific policy for the PCI feature CTO
> +value range
> +  or disable
> +
> +  @param  CtoSupport    value corresponding to data type
> EFI_PCI_CONF_CTO_SUPPORT
> +  @param  PciDevice     A pointer to PCI_IO_DEVICE
> +**/
> +VOID
> +SetDevicePolicyCTO (
> +  IN  EFI_PCI_CONF_CTO_SUPPORT    CtoSupport,
> +  OUT PCI_IO_DEVICE               *PciDevice
> +)
> +{
> +  //
> +  // implementation specific rules for the usage of PCI_FEATURE_POLICY
> +members
> +  // exclusively for the PCI Feature CTO
> +  //
> +  // .Override = 0 to skip this PCI feature CTO for the PCI device
> +  // .Override = 1 to program this CTO PCI feature
> +  //      .Act = 1 to program the CTO range as per given device policy in .Support
> +  //      .Act = 0 to disable the CTO mechanism in the PCI device, CTO set to
> default range
> +  //
> +  switch (CtoSupport) {
> +    case  EFI_PCI_CONF_CTO_AUTO:
> +      PciDevice->SetupCTO.Override = 0;
> +      break;
> +    case  EFI_PCI_CONF_CTO_DEFAULT:
> +      PciDevice->SetupCTO.Override = 1;
> +      PciDevice->SetupCTO.Act = 1;
> +      PciDevice->SetupCTO.Support =
> PCIE_COMPLETION_TIMEOUT_50US_50MS;
> +      break;
> +    case  EFI_PCI_CONF_CTO_RANGE_A1:
> +      PciDevice->SetupCTO.Override = 1;
> +      PciDevice->SetupCTO.Act = 1;
> +      PciDevice->SetupCTO.Support =
> PCIE_COMPLETION_TIMEOUT_50US_100US;
> +      break;
> +    case  EFI_PCI_CONF_CTO_RANGE_A2:
> +      PciDevice->SetupCTO.Override = 1;
> +      PciDevice->SetupCTO.Act = 1;
> +      PciDevice->SetupCTO.Support = PCIE_COMPLETION_TIMEOUT_1MS_10MS;
> +      break;
> +    case  EFI_PCI_CONF_CTO_RANGE_B1:
> +      PciDevice->SetupCTO.Override = 1;
> +      PciDevice->SetupCTO.Act = 1;
> +      PciDevice->SetupCTO.Support =
> PCIE_COMPLETION_TIMEOUT_16MS_55MS;
> +      break;
> +    case  EFI_PCI_CONF_CTO_RANGE_B2:
> +      PciDevice->SetupCTO.Override = 1;
> +      PciDevice->SetupCTO.Act = 1;
> +      PciDevice->SetupCTO.Support =
> PCIE_COMPLETION_TIMEOUT_65MS_210MS;
> +      break;
> +    case  EFI_PCI_CONF_CTO_RANGE_C1:
> +      PciDevice->SetupCTO.Override = 1;
> +      PciDevice->SetupCTO.Act = 1;
> +      PciDevice->SetupCTO.Support =
> PCIE_COMPLETION_TIMEOUT_260MS_900MS;
> +      break;
> +    case  EFI_PCI_CONF_CTO_RANGE_C2:
> +      PciDevice->SetupCTO.Override = 1;
> +      PciDevice->SetupCTO.Act = 1;
> +      PciDevice->SetupCTO.Support = PCIE_COMPLETION_TIMEOUT_1S_3_5S;
> +      break;
> +    case  EFI_PCI_CONF_CTO_RANGE_D1:
> +      PciDevice->SetupCTO.Override = 1;
> +      PciDevice->SetupCTO.Act = 1;
> +      PciDevice->SetupCTO.Support = PCIE_COMPLETION_TIMEOUT_4S_13S;
> +      break;
> +    case  EFI_PCI_CONF_CTO_RANGE_D2:
> +      PciDevice->SetupCTO.Override = 1;
> +      PciDevice->SetupCTO.Act = 1;
> +      PciDevice->SetupCTO.Support = PCIE_COMPLETION_TIMEOUT_17S_64S;
> +      break;
> +    case  EFI_PCI_CONF_CTO_DET_DISABLE:
> +      PciDevice->SetupCTO.Override = 1;
> +      PciDevice->SetupCTO.Act = 0;
> +      PciDevice->SetupCTO.Support =
> PCIE_COMPLETION_TIMEOUT_50US_50MS;
> +      break;
> +  }
> +}
> +
>  /**
>    Generic routine to setup the PCI features as per its predetermined defaults.
>  **/
> @@ -561,6 +640,7 @@ SetupDefaultsDevicePlatformPolicy (
>    PciDevice->SetupMRRS = EFI_PCI_CONF_MAX_READ_REQ_SIZE_AUTO;
>    PciDevice->SetupRO.Override = 0;
>    PciDevice->SetupNS.Override = 0;
> +  PciDevice->SetupCTO.Override = 0;
>  }
> 
>  /**
> @@ -606,6 +686,10 @@ GetPciDevicePlatformPolicyEx (
>        // set the device specific policy for No-Snoop
>        //
>        SetDevicePolicyNoSnoop (PciPlatformExtendedPolicy.DeviceCtlNoSnoop,
> PciIoDevice);
> +      //
> +      // set the device specific policy for Completion Timeout (CTO)
> +      //
> +      SetDevicePolicyCTO (PciPlatformExtendedPolicy.CTOsupport,
> + PciIoDevice);
> 
>        DEBUG ((
>            DEBUG_INFO, "[device policy: platform]"
> --
> 2.21.0.windows.1
> 
> 
> 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe:New PCI features separation with PCD
  2019-11-13  3:22   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe:New PCI features separation with PCD Javeed, Ashraf
@ 2019-12-16 12:46     ` Ni, Ray
  0 siblings, 0 replies; 51+ messages in thread
From: Ni, Ray @ 2019-12-16 12:46 UTC (permalink / raw)
  To: Javeed, Ashraf, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

With the new protocol discussed in https://bugzilla.tianocore.org/show_bug.cgi?id=1954,
this patch review is skipped.


> -----Original Message-----
> From: Javeed, Ashraf <ashraf.javeed@intel.com>
> Sent: Wednesday, November 13, 2019 11:22 AM
> To: devel@edk2.groups.io; Javeed, Ashraf <ashraf.javeed@intel.com>
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>; Ni, Ray <ray.ni@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe:New PCI features
> separation with PCD
> 
> This patch is also uploaded in the following Repo:-
> https://github.com/ashrafj/edk2-staging/commit/0cc1a9555e1546ad94dd368160ece526d10d96a6
> 
> Please review.
> Thanks
> Ashraf
> 
> > -----Original Message-----
> > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> > Ashraf
> > Sent: Friday, November 1, 2019 8:40 PM
> > To: devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> > Ni, Ray <ray.ni@intel.com>
> > Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12]
> > MdeModulePkg/PciBusDxe:New PCI features separation with PCD
> >
> > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> >
> > Definition of bit masks for the new PCD for the following new PCI feature
> > set:-
> > 1.	Maximum Payload Size (MPS)
> > 2.	Maximum Read Request Size (MRRS)
> > 3.	Completion Timeout (CTO)
> > 4.	Relax Order (RO) Enable
> > 5.	No Snoop (NS) Enable
> > 6.	Extended Tag
> > 7.	ASPM support
> > 8.	Common Clock Configuration
> > 9.	Extended SYNC
> > 10.	Atomic Op
> > 11.	LTR Enable
> > 12.	PTM support
> >
> > Code changes made to the PCI Bus driver to adopt to these new PCD defini- tion,
> > helper routines defined for features that needs to be supported in.
> > future.
> >
> > 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/PciBusDxe.inf       |   5 ++++-
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c | 177
> > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > +++++++++++++++++++++++++++++++++++++++++++++++
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h |  26
> > ++++++++++++++++++++++++++
> >  MdeModulePkg/MdeModulePkg.dec                      |  22
> > ++++++++++++++++++++++
> >  4 files changed, 229 insertions(+), 1 deletion(-)
> >
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > index 05c2202..6dab970 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,8 @@
> >    PciCommand.h
> >    PciIo.h
> >    PciBus.h
> > +  PciFeatureSupport.c
> > +  PciFeatureSupport.h
> >
> >  [Packages]
> >    MdePkg/MdePkg.dec
> > @@ -104,6 +106,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/PciFeatureSupport.c
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > new file mode 100644
> > index 0000000..8be227a
> > --- /dev/null
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > @@ -0,0 +1,177 @@
> > +/** @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 "PciBus.h"
> > +#include "PciFeatureSupport.h"
> > +
> > +/**
> > +  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; }
> > +
> > +/**
> > +  Main routine to indicate whether the platform has selected the Relax
> > +Ordering
> > +  PCI feature to be configured by this driver
> > +
> > +  @retval TRUE    platform has selected the Relax Ordering to be configured
> > +          FALSE   platform has not selected this feature
> > +**/
> > +BOOLEAN
> > +SetupRelaxOrder (
> > +  )
> > +{
> > +  return (PcdGet32 (PcdOtherPciFeatures) & PCI_FEATURE_SUPPORT_FLAG_RO)
> > +? TRUE : FALSE; }
> > +
> > +/**
> > +  Main routine to indicate whether the platform has selected the
> > +No-Snoop
> > +  PCI feature to be configured by this driver
> > +
> > +  @retval TRUE    platform has selected the No-Snoop to be configured
> > +          FALSE   platform has not selected this feature
> > +**/
> > +BOOLEAN
> > +SetupNoSnoop (
> > +  )
> > +{
> > +  return (PcdGet32 (PcdOtherPciFeatures) & PCI_FEATURE_SUPPORT_FLAG_NS)
> > +? TRUE : FALSE; }
> > +
> > +/**
> > +  Main routine to indicate whether the platform has selected the
> > +Completion Timeout
> > +  PCI feature to be configured by this driver
> > +
> > +  @retval TRUE    platform has selected the Completion Timeout to be
> > configured
> > +          FALSE   platform has not selected this feature
> > +**/
> > +BOOLEAN
> > +SetupCompletionTimeout (
> > +  )
> > +{
> > +  return (PcdGet32 (PcdOtherPciFeatures) &
> > +PCI_FEATURE_SUPPORT_FLAG_CTO) ? TRUE : FALSE; }
> > +
> > +/**
> > +  Main routine to indicate whether the platform has selected the
> > +Extended Tag
> > +  PCI feature to be configured by this driver
> > +
> > +  @retval TRUE    platform has selected the Completion Timeout to be
> > configured
> > +          FALSE   platform has not selected this feature
> > +**/
> > +BOOLEAN
> > +SetupExtendedTag (
> > +  )
> > +{
> > +  return (PcdGet32 (PcdOtherPciFeatures) &
> > +PCI_FEATURE_SUPPORT_FLAG_ETAG) ? TRUE : FALSE; }
> > +
> > +/**
> > +  Main routine to indicate whether the platform has selected the Atomic
> > +Op
> > +  PCI feature to be configured by this driver
> > +
> > +  @retval TRUE    platform has selected the Completion Timeout to be
> > configured
> > +          FALSE   platform has not selected this feature
> > +**/
> > +BOOLEAN
> > +SetupAtomicOp (
> > +  )
> > +{
> > +  return (PcdGet32 (PcdOtherPciFeatures) &
> > +PCI_FEATURE_SUPPORT_FLAG_AOP) ? TRUE : FALSE; }
> > +/**
> > +  Main routine to indicate whether the platform has selected the LTR
> > +  PCI feature to be configured by this driver
> > +
> > +  @retval TRUE    platform has selected the Completion Timeout to be
> > configured
> > +          FALSE   platform has not selected this feature
> > +**/
> > +BOOLEAN
> > +SetupLtr (
> > +  )
> > +{
> > +  return (PcdGet32 (PcdOtherPciFeatures) &
> > +PCI_FEATURE_SUPPORT_FLAG_LTR) ? TRUE : FALSE; }
> > +
> > +/**
> > +  Main routine to indicate whether the platform has selected the ASPM
> > +state
> > +  PCI feature to be configured by this driver
> > +
> > +  @retval TRUE    platform has selected the Completion Timeout to be
> > configured
> > +          FALSE   platform has not selected this feature
> > +**/
> > +BOOLEAN
> > +SetupAspm (
> > +  )
> > +{
> > +  return (PcdGet32 (PcdOtherPciFeatures) &
> > +PCI_FEATURE_SUPPORT_FLAG_ASPM) ? TRUE : FALSE; }
> > +
> > +/**
> > +  Main routine to indicate whether the platform has selected the Common
> > +Clock Configuration
> > +  PCI feature to be configured by this driver
> > +
> > +  @retval TRUE    platform has selected the Completion Timeout to be
> > configured
> > +          FALSE   platform has not selected this feature
> > +**/
> > +BOOLEAN
> > +SetupCommonClkCfg (
> > +  )
> > +{
> > +  return (PcdGet32 (PcdOtherPciFeatures) &
> > +PCI_FEATURE_SUPPORT_FLAG_CCC) ? TRUE : FALSE; }
> > +
> > +/**
> > +  Main routine to indicate whether the platform has selected the
> > +Extended Synch
> > +  PCI feature to be configured by this driver
> > +
> > +  @retval TRUE    platform has selected the Completion Timeout to be
> > configured
> > +          FALSE   platform has not selected this feature
> > +**/
> > +BOOLEAN
> > +SetupExtendedSynch (
> > +  )
> > +{
> > +  return (PcdGet32 (PcdOtherPciFeatures) &
> > +PCI_FEATURE_SUPPORT_FLAG_ESYN) ? TRUE : FALSE; }
> > +
> > +/**
> > +  Main routine to indicate whether the platform has selected the PIM
> > +Control
> > +  PCI feature to be configured by this driver
> > +
> > +  @retval TRUE    platform has selected the Completion Timeout to be
> > configured
> > +          FALSE   platform has not selected this feature
> > +**/
> > +BOOLEAN
> > +SetupPtm (
> > +  )
> > +{
> > +  return (PcdGet32 (PcdOtherPciFeatures) &
> > +PCI_FEATURE_SUPPORT_FLAG_PTM) ? TRUE : FALSE; }
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > new file mode 100644
> > index 0000000..d06a5e8
> > --- /dev/null
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > @@ -0,0 +1,26 @@
> > +/** @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_
> > +//
> > +// Macro definitions for the PCI Features support PCD // #define
> > +PCI_FEATURE_SUPPORT_FLAG_MPS  BIT0 #define
> > +PCI_FEATURE_SUPPORT_FLAG_MRRS BIT1
> > +#define PCI_FEATURE_SUPPORT_FLAG_RO   BIT2
> > +#define PCI_FEATURE_SUPPORT_FLAG_NS   BIT3
> > +#define PCI_FEATURE_SUPPORT_FLAG_CTO  BIT4 #define
> > +PCI_FEATURE_SUPPORT_FLAG_ETAG BIT5 #define
> > PCI_FEATURE_SUPPORT_FLAG_AOP
> > +BIT6 #define PCI_FEATURE_SUPPORT_FLAG_LTR  BIT7 #define
> > +PCI_FEATURE_SUPPORT_FLAG_ASPM BIT12 #define
> > +PCI_FEATURE_SUPPORT_FLAG_CCC  BIT13 #define
> > +PCI_FEATURE_SUPPORT_FLAG_ESYN BIT14 #define
> > +PCI_FEATURE_SUPPORT_FLAG_PTM  BIT20 #endif
> > diff --git a/MdeModulePkg/MdeModulePkg.dec
> > b/MdeModulePkg/MdeModulePkg.dec index 12e0bbf..ed82e85 100644
> > --- a/MdeModulePkg/MdeModulePkg.dec
> > +++ b/MdeModulePkg/MdeModulePkg.dec
> > @@ -1036,6 +1036,28 @@
> >    # @Prompt Enable UEFI Stack Guard.
> >
> > gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard|FALSE|BOOLEAN|0x30
> > 001055
> >
> > +  ## 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 - if set, the PCI Bus driver programs the device's Relax Ordering
> > state.<BR>
> > +  #   Bit 3 - if set, the PCI Bus driver programs the device's No-Snoop state.<BR>
> > +  #   Bit 4 - if set, the PCI Bus driver programs the device's Completion Timeout
> > range.<BR>
> > +  #   Bit 5 - if set, the PCI Bus driver programs the device's Extended Tag
> > range.<BR>
> > +  #   Bit 6 - if set, the PCI Bus driver programs the device's AtomicOp
> > feature.<BR>
> > +  #   Bit 7 - if set, the PCI Bus driver programs the device's LTR feature.<BR>
> > +  #   Bit 8 to 11 - Reserved for future use by the PCI Bus driver.<BR>
> > +  #   Bit 12 - if set, the PCI Bus driver programs the PCIe link ASPM state.<BR>
> > +  #   Bit 13 - if set, the PCI Bus driver programs the PCIe link Common Clock
> > Configuration.<BR>
> > +  #   Bit 14 - if set, the PCI Bus driver programs the PCIe link Extended Synch
> > state.<BR>
> > +  #   Bit 15 to 19 - Reserved for future use by the PCI Bus driver.<BR>
> > +  #   Bit 20 - if set, the PCI Bus driver programs the device's PTM feature.<BR>
> > +  #   Bit 21 to 31 - Reserved for future use by the PCI Bus driver.<BR>
> > +  # @Prompt The UEFI PCI Bus driver enables the new set of other PCI Features.
> > +
> > +
> > gEfiMdeModulePkgTokenSpaceGuid.PcdOtherPciFeatures|0x001070FF|UINT32|
> > 0
> > + x30001056
> > +
> >  [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	[flat|nested] 51+ messages in thread

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12] PciBusDxe: Reorganize the PCI Platform Protocol usage code
  2019-11-13  3:23   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12] PciBusDxe: Reorganize the PCI Platform Protocol usage code Javeed, Ashraf
@ 2019-12-16 12:46     ` Ni, Ray
  0 siblings, 0 replies; 51+ messages in thread
From: Ni, Ray @ 2019-12-16 12:46 UTC (permalink / raw)
  To: Javeed, Ashraf, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

With comments in https://bugzilla.tianocore.org/show_bug.cgi?id=1954,
a new PCIE Override protocol will be added.
So this patch review is skipped.


> -----Original Message-----
> From: Javeed, Ashraf <ashraf.javeed@intel.com>
> Sent: Wednesday, November 13, 2019 11:24 AM
> To: devel@edk2.groups.io; Javeed, Ashraf <ashraf.javeed@intel.com>
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>; Ni, Ray <ray.ni@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12] PciBusDxe: Reorganize the PCI Platform
> Protocol usage code
> 
> This patch is also uploaded in the following Repo, for review:-
> https://github.com/ashrafj/edk2-staging/commit/ff68bb88bdb81d3921ebc7410c69e52e9d2fdb0e
> 
> Thanks
> Ashraf
> 
> > -----Original Message-----
> > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Javeed,
> > Ashraf
> > Sent: Friday, November 1, 2019 8:40 PM
> > To: devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>;
> > Ni, Ray <ray.ni@intel.com>
> > Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12]
> > PciBusDxe: Reorganize the PCI Platform Protocol usage code
> >
> > BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2194
> >
> > The following legacy PCI Platform Protocol usage is reorganized in the separate
> > source files:-
> > (1) PlatformPrepController
> > (2) PlatformNotify
> > (3) GetPlatformPolicy
> > (4) GetPciRom
> >
> > This code changes are made to support the new PCI Platform Protocol along
> > with the existing legacy interface in the PCI Bus driver.
> >
> > 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             |   3 +--
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf        |   2 ++
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c   |  58 +++++++++++-----
> > ------------------------------------------
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c      | 139
> > +++++++++++++++++++++++++++++++++------------------------------------------------
> > ----------------------------------------------------------
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 254
> > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h | 109
> > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > ++++++++++++++++++++++++++++++++++++++++++++
> >  MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c |  15 +--------------
> >  8 files changed, 413 insertions(+), 190 deletions(-)
> >
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
> > index b020ce5..45cd64d 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
> > -          );
> > -  }
> > +  LocatePciPlatformProtocol ();
> >
> >    if (mIoMmuProtocol == NULL) {
> >      gBS->LocateProtocol (
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > index 504a1b1..141c158 100644
> > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
> > @@ -79,6 +79,7 @@ typedef enum {
> >  #include "PciPowerManagement.h"
> >  #include "PciHotPlugSupport.h"
> >  #include "PciLib.h"
> > +#include "PciPlatformSupport.h"
> >
> >  #define VGABASE1  0x3B0
> >  #define VGALIMIT1 0x3BB
> > @@ -307,8 +308,6 @@ extern UINTN
> > gPciHostBridgeNumber;
> >  extern EFI_HANDLE
> > gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM];
> >  extern UINT64                                       gAllOne;
> >  extern UINT64                                       gAllZero;
> > -extern EFI_PCI_PLATFORM_PROTOCOL                    *gPciPlatformProtocol;
> > -extern EFI_PCI_OVERRIDE_PROTOCOL                    *gPciOverrideProtocol;
> >  extern BOOLEAN                                      mReserveIsaAliases;
> >  extern BOOLEAN                                      mReserveVgaAliases;
> >
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > index 6dab970..4ce99ce 100644
> > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
> > @@ -59,6 +59,8 @@
> >    PciBus.h
> >    PciFeatureSupport.c
> >    PciFeatureSupport.h
> > +  PciPlatformSupport.c
> > +  PciPlatformSupport.h
> >
> >  [Packages]
> >    MdePkg/MdePkg.dec
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > index b7832c6..149a120 100644
> > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
> > @@ -208,8 +208,6 @@ RegisterPciDevice (
> >    )
> >  {
> >    EFI_STATUS          Status;
> > -  VOID                *PlatformOpRomBuffer;
> > -  UINTN               PlatformOpRomSize;
> >    EFI_PCI_IO_PROTOCOL *PciIo;
> >    UINT8               Data8;
> >    BOOLEAN             HasEfiImage;
> > @@ -244,49 +242,16 @@ 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 +259,7 @@ RegisterPciDevice (
> >            PciIoDevice->FunctionNumber,
> >            PciIoDevice->PciIo.RomImage,
> >            PciIoDevice->PciIo.RomSize
> > -          );
> > -      }
> > +        );
> >      }
> >    }
> >
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
> > index 8db1ebf..aef8a3b 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/PciPlatformSupport.c
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > new file mode 100644
> > index 0000000..6f95794
> > --- /dev/null
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > @@ -0,0 +1,254 @@
> > +/** @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 "PciBus.h"
> > +
> > +EFI_PCI_PLATFORM_PROTOCOL                     *mPciPlatformProtocol;
> > +EFI_PCI_OVERRIDE_PROTOCOL                     *mPciOverrideProtocol;
> > +
> > +
> > +
> > +/**
> > +  This function retrieves the PCI Platform Protocol published by
> > +platform driver
> > +
> > +**/
> > +VOID
> > +LocatePciPlatformProtocol (
> > +  )
> > +{
> > +    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 (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 (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 (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 (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 (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;
> > +}
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > new file mode 100644
> > index 0000000..c0d3b49
> > --- /dev/null
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > @@ -0,0 +1,109 @@
> > +/** @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_
> > +
> > +/**
> > +  This function retrieves the PCI Platform Protocol published by
> > +platform driver
> > +
> > +**/
> > +VOID
> > +LocatePciPlatformProtocol (
> > +  );
> > +
> > +/**
> > +  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
> > +  );
> > +
> > +#endif
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
> > index 4969ee0..be6f42a 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;
> > --
> > 2.21.0.windows.1
> >
> >
> > 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12] PciBusDxe: Separation of the PCI device registration and start
  2019-11-13  3:25   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12] PciBusDxe: Separation of the PCI device registration and start Javeed, Ashraf
@ 2019-12-17  1:38     ` Ni, Ray
  2019-12-17  3:19       ` Javeed, Ashraf
  0 siblings, 1 reply; 51+ messages in thread
From: Ni, Ray @ 2019-12-17  1:38 UTC (permalink / raw)
  To: Javeed, Ashraf, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

Ashraf,
The change looks good.

2 minor comments:
1. StartPciRootPortsOnBridge()
     Can it be renamed to EnablePciDevicesOnBridge()?
     Because it basically calls PciIo.Attribute() to enable the devices. And I am not sure the enable only applies to PCI root ports. There could be PCI devices behind P2P bridge.

2. +  if (EFI_ERROR (Status) == EFI_NOT_FOUND) {
    Should be "if (EFI_ERROR (Status)) {"

> >  EFI_STATUS
> > -StartPciDevicesOnBridge (
> > +StartPciRootPortsOnBridge (
> > +  IN EFI_HANDLE                          Controller,
> > +  IN PCI_IO_DEVICE                       *RootBridge
> > +  )
 > +  if (EFI_ERROR (Status) == EFI_NOT_FOUND) {
> > +    return Status;
> > +  } else {
> > +    //
> > +    // 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.
> > --
> > 2.21.0.windows.1
> >
> >
> > 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12] PciBusDxe: Separation of the PCI device registration and start
  2019-12-17  1:38     ` Ni, Ray
@ 2019-12-17  3:19       ` Javeed, Ashraf
  2019-12-19  1:34         ` Ni, Ray
  0 siblings, 1 reply; 51+ messages in thread
From: Javeed, Ashraf @ 2019-12-17  3:19 UTC (permalink / raw)
  To: Ni, Ray, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

My response in line.
Thanks
Ashraf

> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Tuesday, December 17, 2019 7:08 AM
> To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12]
> PciBusDxe: Separation of the PCI device registration and start
> 
> Ashraf,
> The change looks good.
> 
> 2 minor comments:
> 1. StartPciRootPortsOnBridge()
>      Can it be renamed to EnablePciDevicesOnBridge()?
>      Because it basically calls PciIo.Attribute() to enable the devices. And I am not
> sure the enable only applies to PCI root ports. There could be PCI devices behind
> P2P bridge.
It enables only Type 1 PCI devices (Root Port, PCIe-to-PCI Bridge, PCIe switch upstream/downstream ports), and no endpoint (Type 0) devices.

> 
> 2. +  if (EFI_ERROR (Status) == EFI_NOT_FOUND) {
>     Should be "if (EFI_ERROR (Status)) {"
Good catch! Will fix this.
> 
> > >  EFI_STATUS
> > > -StartPciDevicesOnBridge (
> > > +StartPciRootPortsOnBridge (
> > > +  IN EFI_HANDLE                          Controller,
> > > +  IN PCI_IO_DEVICE                       *RootBridge
> > > +  )
>  > +  if (EFI_ERROR (Status) == EFI_NOT_FOUND) {
> > > +    return Status;
> > > +  } else {
> > > +    //
> > > +    // 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.
> > > --
> > > 2.21.0.windows.1
> > >
> > >
> > > 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
  2019-11-13  3:27   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration Javeed, Ashraf
@ 2019-12-17 11:56     ` Ni, Ray
  2019-12-18  7:14       ` Javeed, Ashraf
  0 siblings, 1 reply; 51+ messages in thread
From: Ni, Ray @ 2019-12-17 11:56 UTC (permalink / raw)
  To: Javeed, Ashraf, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

Please check comments below.
I may have more comments regarding to the four phases after I finish review of further patches.

Besides the comments below, I have a general comments to the debug message: can you please
review the existing debug message in the PciBus driver and make sure your newly added debug message
aligns to existing style. And try to use less lines of debug messages with still enough debug information.

> > +PRIMARY_ROOT_PORT_NODE                      *mPrimaryRootPortList;
> > +
> > +/**
> > +  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;

1. Please follow existing linked list usage style. The first node in the list is an empty header node.

LIST_ENTRY   mPrimaryRootPortList;
LIST_ENTRY   mPciFeaturesConfigurationCompletionList;

> > +BOOLEAN
> > +CheckPciFeatureConfigurationRecordExist (
> > +  IN  PCI_IO_DEVICE                             *RootBridge,
> > +  OUT PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > +**PciFeatureConfigRecord
> > +  )

2. Is this function to check whether the PCIE features under a root bridge
is already initialized?
Can you use the existing variable gFullEnumeration?
The variable is set to TRUE when the enumeration is done to a host bridge in the first time.
By using gFullEnumeration, the entire function is not needed.

> > +EFI_STATUS AddRootBridgeInPciFeaturesConfigCompletionList (
> > +  IN PCI_IO_DEVICE          *RootBridge,
> > +  IN BOOLEAN                ReEnumerationRequired
> > +  )

3. Same question as #2. I think by using gFullEnumeration, this function is not needed.


> > +BOOLEAN
> > +IsPciRootPortEmpty (
> > +  IN  PCI_IO_DEVICE                           *PciDevice
> > +  )

4. Please use IsListEmpty() directly from callers and remove this function.

> > +**/
> > +EFI_STATUS
> > +EnumerateOtherPciFeatures (

5. Can it be "EnumeratePcieFeatures"?

> > +  IN PCI_IO_DEVICE          *RootBridge
> > +  )
> > +{
> > +  EFI_STATUS            Status;
> > +  UINTN                 OtherPciFeatureConfigPhase;
> > +
> > +  //
> > +  // check on PCI features configuration is complete and re-enumeration
> > + is required  //  if (!CheckPciFeaturesConfigurationRequired
> > + (RootBridge)) {
> > +    return EFI_ALREADY_STARTED;
> > +  }
> > +
 > > +  CHAR16                *Str;
> > +  Str = ConvertDevicePathToText (
> > +          DevicePathFromHandle (RootBridge->Handle),
> > +          FALSE,
> > +          FALSE
> > +        );
> > +  DEBUG ((DEBUG_INFO, "Enumerating PCI features for Root Bridge %s\n",
> > + Str != NULL ? Str : L""));

6. Please use DEBUG_CODE macro to include ConvertDevicePathToText() and DEBUG().
Please remember to call FreePool().

> > +
> > +  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);

7. How about "RecordPciRootPorts (RootBridge)"? The "Bridges" suffix is a bit confusing.

> > +      case  PciFeatureGetDevicePolicy:
> > +      case  PciFeatureSetupPhase:

8. In SetupPciFeatures(), why do you need to call DeviceExist()?
Did you see any case that a device is detected in the beginning of PciBus scan but
is hidden when calling SetupPciFeatures()?

9. In GetPciFeaturesConfigurationTable() when checking whether a PCI device
belongs to a root port, we can use below simpler logic:
  SizeOfPciDevicePath = GetDevicePathSize (PciDevicePath);
  SizeOfRootPortDevicePath = GetDevicePathSize (RootPortPath);
  if ((SizeOfRootPortDevicePath < SizeOfPciDevicePath) &&
      CompareMem (PciDevicePath, RootPortPath, SizeOfRootPortDevicePath - END_DEVICE_PATH_LENGTH) == 0)) {
    // PCI device belongs to the root port.
  }

> > +        Status = ProgramPciFeatures (RootBridge);
10. ProgramPcieFeatures()?

> > +
> > +  if (Str != NULL) {
> > +    FreePool (Str);
> > +  }

11. OK the Str is freed here because Str is needed for other debug messages inside the function.

> > +  //
> > +  // mark this root bridge as PCI features configuration complete, and
> > +no new
> > +  // enumeration is required
> > +  //
> > +  AddRootBridgeInPciFeaturesConfigCompletionList (RootBridge, FALSE);

12. Not needed.

> > +_PRIMARY_ROOT_PORT_NODE {

> > +  //
> > +  // Signature header
> > +  //
> > +  UINT32                                    Signature;
> > +  //
> > +  // linked list pointers to next node
> > +  //
> > +  LIST_ENTRY                                NeighborRootPort;
> > +  //
> > +  // pointer to PCI_IO_DEVICE of the primary PCI Controller device
> > +  //
> > +  EFI_DEVICE_PATH_PROTOCOL                  *RootPortDevicePath;
> > +  //
> > +  // pointer to the corresponding PCI feature configuration Table node
> > +  // all the child PCI devices of the controller are aligned based on
> > +this table
> > +  //
> > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > *OtherPciFeaturesConfigurationTable;
> > +};

13. Can you add the OTHER_PCI_FEATURES_CONFIGURATION_TABLE field to PCI_IO_DEVICE structure?
So this structure PRIMARY_ROOT_PORT_NODE is not needed.

> > +struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
14. This structure is not needed if using gFullEnumeration.

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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 06/12] PciBusDxe: Integration of setup for PCI feature enumeration
  2019-11-13  3:28   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 06/12] PciBusDxe: Integration of setup " Javeed, Ashraf
@ 2019-12-17 11:59     ` Ni, Ray
  2019-12-18  7:15       ` Javeed, Ashraf
  0 siblings, 1 reply; 51+ messages in thread
From: Ni, Ray @ 2019-12-17 11:59 UTC (permalink / raw)
  To: Javeed, Ashraf, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A


> > +    if (CheckOtherPciFeaturesPcd ()) {
> > +      //
> > +      // the late configuration of PCI features
> > +      //
> > +      Status = EnumerateOtherPciFeatures (
> > +                  RootBridge
> > +                );

The function name can be "ProgramPcieFeatures"?

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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] PciBusDxe: Record the PCI-Express Capability Structure
  2019-11-13  3:29   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] PciBusDxe: Record the PCI-Express Capability Structure Javeed, Ashraf
@ 2019-12-17 12:03     ` Ni, Ray
  2019-12-18  7:32       ` Javeed, Ashraf
  0 siblings, 1 reply; 51+ messages in thread
From: Ni, Ray @ 2019-12-17 12:03 UTC (permalink / raw)
  To: Javeed, Ashraf, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

2 minor comments.

And I suggest you don't change EFI_D_xxx in this patch. Or you could change in a separate patch.

> > +  PCI_CAPABILITY_PCIEXP                     PciExpStruct;

1. to align "Pci" which buffers the PCI config space, this can be simply "PciExp".

> > +  //
> > +  // For SR-IOV
> > +  //
> >    UINT32                                    AriCapabilityOffset;
> >    UINT32                                    SrIovCapabilityOffset;
> >    UINT32                                    MrIovCapabilityOffset;
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > index c7eafff..2343702 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
> > +                );

2. Please follow EDKII coding style document regarding the indent.

> >    }
> >
> >    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
> > index 9e6671d..df9e696 100644
> > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > @@ -467,6 +467,14 @@ GetPciFeaturesConfigurationTable (
> >      return EFI_SUCCESS;
> >    }
> >
> > +  //
> > +  // 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;
> > +  }
> >
> >    if (IsDevicePathEnd (PciDevice->DevicePath)){
> >      //
> > @@ -575,6 +583,45 @@ IsPciRootPortEmpty (  }
> >
> >
> > +/**
> > +  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.
> >
> > @@ -590,8 +637,12 @@ SetupDevicePciFeatures (
> >    )
> >  {
> >    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)) {
> > --
> > 2.21.0.windows.1
> >
> >
> > 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
  2019-12-17 11:56     ` Ni, Ray
@ 2019-12-18  7:14       ` Javeed, Ashraf
  2019-12-19  5:48         ` Ni, Ray
       [not found]         ` <15E1AFB3EABD031C.30484@groups.io>
  0 siblings, 2 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-12-18  7:14 UTC (permalink / raw)
  To: Ni, Ray, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

Thanks for the review, Ray!
My response in line

> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Tuesday, December 17, 2019 5:26 PM
> To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12]
> PciBusDxe: Setup sub-phases for PCI feature enumeration
> 
> Please check comments below.
> I may have more comments regarding to the four phases after I finish review of
> further patches.
> 
> Besides the comments below, I have a general comments to the debug
> message: can you please review the existing debug message in the PciBus driver
> and make sure your newly added debug message aligns to existing style. And try
> to use less lines of debug messages with still enough debug information.
Ok, will look into that.

> 
> > > +PRIMARY_ROOT_PORT_NODE                      *mPrimaryRootPortList;
> > > +
> > > +/**
> > > +  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;
> 
> 1. Please follow existing linked list usage style. The first node in the list is an
> empty header node.
> 
> LIST_ENTRY   mPrimaryRootPortList;
> LIST_ENTRY   mPciFeaturesConfigurationCompletionList;
> 
Ok, will make the change when I incorporate the ECR 0.75 or greater version.

> > > +BOOLEAN
> > > +CheckPciFeatureConfigurationRecordExist (
> > > +  IN  PCI_IO_DEVICE                             *RootBridge,
> > > +  OUT PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > +**PciFeatureConfigRecord
> > > +  )
> 
> 2. Is this function to check whether the PCIE features under a root bridge is
> already initialized?
> Can you use the existing variable gFullEnumeration?
> The variable is set to TRUE when the enumeration is done to a host bridge in the
> first time.
> By using gFullEnumeration, the entire function is not needed.
> 
Ok, will look into this.

> > > +EFI_STATUS AddRootBridgeInPciFeaturesConfigCompletionList (
> > > +  IN PCI_IO_DEVICE          *RootBridge,
> > > +  IN BOOLEAN                ReEnumerationRequired
> > > +  )
> 
> 3. Same question as #2. I think by using gFullEnumeration, this function is not
> needed.
> 
OK

> 
> > > +BOOLEAN
> > > +IsPciRootPortEmpty (
> > > +  IN  PCI_IO_DEVICE                           *PciDevice
> > > +  )
> 
> 4. Please use IsListEmpty() directly from callers and remove this function.
> 
Will consider this.

> > > +**/
> > > +EFI_STATUS
> > > +EnumerateOtherPciFeatures (
> 
> 5. Can it be "EnumeratePcieFeatures"?
> 
Yes, with the change to ECR 0.75, this routine name shall be changed.

> > > +  IN PCI_IO_DEVICE          *RootBridge
> > > +  )
> > > +{
> > > +  EFI_STATUS            Status;
> > > +  UINTN                 OtherPciFeatureConfigPhase;
> > > +
> > > +  //
> > > +  // check on PCI features configuration is complete and
> > > + re-enumeration is required  //  if
> > > + (!CheckPciFeaturesConfigurationRequired
> > > + (RootBridge)) {
> > > +    return EFI_ALREADY_STARTED;
> > > +  }
> > > +
>  > > +  CHAR16                *Str;
> > > +  Str = ConvertDevicePathToText (
> > > +          DevicePathFromHandle (RootBridge->Handle),
> > > +          FALSE,
> > > +          FALSE
> > > +        );
> > > +  DEBUG ((DEBUG_INFO, "Enumerating PCI features for Root Bridge
> > > + %s\n", Str != NULL ? Str : L""));
> 
> 6. Please use DEBUG_CODE macro to include ConvertDevicePathToText() and
> DEBUG().
> Please remember to call FreePool().
> 
Ok, will can under DEBUG_CODE, and free pool is called in the end

> > > +
> > > +  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);
> 
> 7. How about "RecordPciRootPorts (RootBridge)"? The "Bridges" suffix is a bit
> confusing.
> 
Fine, will change.

> > > +      case  PciFeatureGetDevicePolicy:
> > > +      case  PciFeatureSetupPhase:
> 
> 8. In SetupPciFeatures(), why do you need to call DeviceExist()?
> Did you see any case that a device is detected in the beginning of PciBus scan
> but is hidden when calling SetupPciFeatures()?
> 
Yes, that is the case; device detected during the beginning of PciBus scan appears to be hidden by the platform drivers, since numerous legacy callbacks are initiated at different phase of PCI enumeration to the PCI Host Bridge, and PciPlatform drivers.
This can be avoided if the PciBus driver is enhanced to check for PCI device existence before the publication of the PCI IO Protocol, and removal of the PCI_IO_DEVICE instance from the linked list.

> 9. In GetPciFeaturesConfigurationTable() when checking whether a PCI device
> belongs to a root port, we can use below simpler logic:
>   SizeOfPciDevicePath = GetDevicePathSize (PciDevicePath);
>   SizeOfRootPortDevicePath = GetDevicePathSize (RootPortPath);
>   if ((SizeOfRootPortDevicePath < SizeOfPciDevicePath) &&
>       CompareMem (PciDevicePath, RootPortPath, SizeOfRootPortDevicePath -
> END_DEVICE_PATH_LENGTH) == 0)) {
>     // PCI device belongs to the root port.
>   }
> 
Ok.

> > > +        Status = ProgramPciFeatures (RootBridge);
> 10. ProgramPcieFeatures()?
> 
OK

> > > +
> > > +  if (Str != NULL) {
> > > +    FreePool (Str);
> > > +  }
> 
> 11. OK the Str is freed here because Str is needed for other debug messages
> inside the function.
> 
Yes

> > > +  //
> > > +  // mark this root bridge as PCI features configuration complete,
> > > +and no new
> > > +  // enumeration is required
> > > +  //
> > > +  AddRootBridgeInPciFeaturesConfigCompletionList (RootBridge,
> > > +FALSE);
> 
> 12. Not needed.
> 
ok, after incorporating the logic of gFullEnumeration it won't be required

> > > +_PRIMARY_ROOT_PORT_NODE {
> 
> > > +  //
> > > +  // Signature header
> > > +  //
> > > +  UINT32                                    Signature;
> > > +  //
> > > +  // linked list pointers to next node
> > > +  //
> > > +  LIST_ENTRY                                NeighborRootPort;
> > > +  //
> > > +  // pointer to PCI_IO_DEVICE of the primary PCI Controller device
> > > +  //
> > > +  EFI_DEVICE_PATH_PROTOCOL                  *RootPortDevicePath;
> > > +  //
> > > +  // pointer to the corresponding PCI feature configuration Table
> > > +node
> > > +  // all the child PCI devices of the controller are aligned based
> > > +on this table
> > > +  //
> > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > *OtherPciFeaturesConfigurationTable;
> > > +};
> 
> 13. Can you add the OTHER_PCI_FEATURES_CONFIGURATION_TABLE field to
> PCI_IO_DEVICE structure?
> So this structure PRIMARY_ROOT_PORT_NODE is not needed.
> 
I think it is better to maintain separately as this configuration table is confined to a group of PCI devices and for the RCiEP it is not applicable hence not required. Moreover, I am maintaining a variable for each PCIe feature in the PCI_IO_DEVICE; perhaps I can consider having just pointer of it....
 
> > > +struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
> 14. This structure is not needed if using gFullEnumeration.
Yes.

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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 06/12] PciBusDxe: Integration of setup for PCI feature enumeration
  2019-12-17 11:59     ` Ni, Ray
@ 2019-12-18  7:15       ` Javeed, Ashraf
  0 siblings, 0 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-12-18  7:15 UTC (permalink / raw)
  To: Ni, Ray, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A



> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Tuesday, December 17, 2019 5:30 PM
> To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 06/12]
> PciBusDxe: Integration of setup for PCI feature enumeration
> 
> 
> > > +    if (CheckOtherPciFeaturesPcd ()) {
> > > +      //
> > > +      // the late configuration of PCI features
> > > +      //
> > > +      Status = EnumerateOtherPciFeatures (
> > > +                  RootBridge
> > > +                );
> 
> The function name can be "ProgramPcieFeatures"?
OK

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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] PciBusDxe: Record the PCI-Express Capability Structure
  2019-12-17 12:03     ` Ni, Ray
@ 2019-12-18  7:32       ` Javeed, Ashraf
  0 siblings, 0 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-12-18  7:32 UTC (permalink / raw)
  To: Ni, Ray, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A



> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Tuesday, December 17, 2019 5:34 PM
> To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12]
> PciBusDxe: Record the PCI-Express Capability Structure
> 
> 2 minor comments.
> 
> And I suggest you don't change EFI_D_xxx in this patch. Or you could change in a
> separate patch.
> 
The below patch check script fails, if I don't change it...
/Git/Tianocore/edk2/BaseTools/Scripts/PatchCheck.py

> > > +  PCI_CAPABILITY_PCIEXP                     PciExpStruct;
> 
> 1. to align "Pci" which buffers the PCI config space, this can be simply "PciExp".
> 
Ok

> > > +  //
> > > +  // For SR-IOV
> > > +  //
> > >    UINT32                                    AriCapabilityOffset;
> > >    UINT32                                    SrIovCapabilityOffset;
> > >    UINT32                                    MrIovCapabilityOffset;
> > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
> > > index c7eafff..2343702 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
> > > PciIoDevice->(
> > >      }
> > >
> > >      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
> > > +                );
> 
> 2. Please follow EDKII coding style document regarding the indent.
> 
Ok, got missed for this routine.

> > >    }
> > >
> > >    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
> > > index 9e6671d..df9e696 100644
> > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
> > > @@ -467,6 +467,14 @@ GetPciFeaturesConfigurationTable (
> > >      return EFI_SUCCESS;
> > >    }
> > >
> > > +  //
> > > +  // 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;
> > > +  }
> > >
> > >    if (IsDevicePathEnd (PciDevice->DevicePath)){
> > >      //
> > > @@ -575,6 +583,45 @@ IsPciRootPortEmpty (  }
> > >
> > >
> > > +/**
> > > +  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.
> > >
> > > @@ -590,8 +637,12 @@ SetupDevicePciFeatures (
> > >    )
> > >  {
> > >    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)) {
> > > --
> > > 2.21.0.windows.1
> > >
> > >
> > > 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12] PciBusDxe: New PCI feature Max_Payload_Size
  2019-11-13  3:30   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12] PciBusDxe: New PCI feature Max_Payload_Size Javeed, Ashraf
@ 2019-12-18  8:38     ` Ni, Ray
  2019-12-18  9:10       ` Ni, Ray
  0 siblings, 1 reply; 51+ messages in thread
From: Ni, Ray @ 2019-12-18  8:38 UTC (permalink / raw)
  To: Javeed, Ashraf, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

> > +  UINT8                                     SetupMPS;
1. Can it be "MaxPayloadSize"?
> > +
> > +  if (PciConfigPhase == PciFeatureGetDevicePolicy) {
> > +    if (SetupMpsAsPerDeviceCapability (PciDevice->SetupMPS)) {

2. Can you replace " SetupMpsAsPerDeviceCapability (PciDevice->SetupMPS" with
"PciDevice->MaxPayloadSize == EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO"?
This makes the code more readable. 

> > +      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;
> > +        }
> > +      }

3. Above two if-s can be simplified as below? and please also copy the spec requirements here as comments.
if (IsListEmpty (&PciDevice->ChildList)) {
  MpsValue = PCIE_MAX_PAYLOAD_SIZE_128B;
}



> > +    } else {
> > +      MpsValue = TranslateMpsSetupValueToPci (PciDevice->SetupMPS);

4. The function name can be "UefiToPciMaxPayloadSize()". And I suggest the
value stored in PciDevice->SetupMPS (MaxPayloadSize) is the macro value
defined in PciExpress21.h. We could do the conversion just after the GetDevicePolicy() call.

> > +    }
> > +    //
> > +    // 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;

5. Max_Payload_Size can be "MaxPayloadSize".
MpsValue can be "MaxPayloadSize".

> > +
> > +    MpsValue = MIN (PciDevice->SetupMPS, MpsValue);
> > +    PciDevice->SetupMPS = MIN (PciDevice->SetupMPS, MpsValue);
> > +
> > +    if (MpsValue != PciFeaturesConfigurationTable->Max_Payload_Size) {
> > +      PciFeaturesConfigurationTable->Max_Payload_Size = MpsValue;
> > +    }
> > +  }

6. Can you simplify the above logic?

> > +
> > +  DEBUG (( DEBUG_INFO,
> > +      "MPS: %d [DevCap:%d],",
> > +      PciDevice->SetupMPS, PciDeviceCap.Bits.MaxPayloadSize
> > +  ));
> > +  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
> > +  )

7. Can this name be "ProgramMaxPayloadSize" because the function does
the register programming?

> > +{
> > +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> > +  UINT32                      Offset;
> > +  EFI_STATUS                  Status;
> > +  EFI_TPL                     OldTpl;
> > +
> > +  PcieDev.Uint16 = 0;
> > +  Offset = PciDevice->PciExpressCapabilityOffset +
> > +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> > + Status = PciDevice->PciIo.Pci.Read (
> > +                                  &PciDevice->PciIo,
> > +                                  EfiPciIoWidthUint16,
> > +                                  Offset,
> > +                                  1,
> > +                                  &PcieDev.Uint16
> > +                                );

8. The PciExp is cached in PciExp field in the PciDevice structure. Why do you need
to read it from HW again?

> > +  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, "MPS=%d,", PciDevice->SetupMPS));
> > +
> > +    //
> > +    // Raise TPL to high level to disable timer interrupt while the write operation
> > completes
> > +    //
> > +    OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
> > +
> > +    Status = PciDevice->PciIo.Pci.Write (
> > +                                    &PciDevice->PciIo,
> > +                                    EfiPciIoWidthUint16,
> > +                                    Offset,
> > +                                    1,
> > +                                    &PcieDev.Uint16
> > +                                  );
> > +    //
> > +    // Restore TPL to its original level
> > +    //
> > +    gBS->RestoreTPL (OldTpl);
> > +
> > +    if (!EFI_ERROR(Status)) {
> > +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> > +    } else {
> > +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) write
> > error!",
> > +          Offset
> > +      ));

9. We can use ASSERT_EFI_ERROR() here. Failure of register writing is a fatal error.

> > +    }
> > +  } else {
> > +    DEBUG (( DEBUG_INFO, "No write of MPS=%d,", PciDevice->SetupMPS));

10. Can we skip this debug message?

> > + }
> > +
> > +  return Status;
> > +}
> >
> >  /**
> >    helper routine to dump the PCIe Device Port Type @@ -669,6 +809,18 @@
> > SetupDevicePciFeatures (
> >      }
> >    }
> >
> > +  DEBUG ((DEBUG_INFO, "["));
> > +  //
> > +  // process the PCI device Max_Payload_Size feature  //  if
> > + (SetupMaxPayloadSize ()) {
> > +    Status = ProcessMaxPayloadSize (
> > +              PciDevice,
> > +              PciConfigPhase,
> > +              OtherPciFeaturesConfigTable
> > +              );

11. Can this function be "CalculatemaxPayloadSize"? Process is too general.

> > +  }
> > +  DEBUG ((DEBUG_INFO, "]\n"));
> >    return Status;
> >  }
> >
> > @@ -765,6 +917,10 @@ ProgramDevicePciFeatures (  {
> >    EFI_STATUS           Status = EFI_SUCCESS;
> >
> > +  if (SetupMaxPayloadSize ()) {
> > +    Status = OverrideMaxPayloadSize (PciDevice);  }  DEBUG ((
> > + DEBUG_INFO, "\n"));
> >    return Status;
> >  }
> >
> > @@ -878,6 +1034,7 @@ AddPrimaryRootPortNode (
> >                      );
> >    if (PciConfigTable) {
> >      PciConfigTable->ID                          = PortNumber;
> > +    PciConfigTable->Max_Payload_Size            =
> > PCIE_MAX_PAYLOAD_SIZE_4096B;
> >    }
> >    RootPortNode->OtherPciFeaturesConfigurationTable  = PciConfigTable;
> >
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > index f92d008..e5ac2a3 100644
> > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > @@ -79,6 +79,11 @@ 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;
> >  };
> >
> >
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > index 238959e..99badd6 100644
> > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > @@ -356,6 +356,63 @@ GetPlatformPciOptionRom (
> >    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;
> > +  }
> > +}
> > +
> > +/**
> > +  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;
> > +  }
> > +}
> > +
> >  /**
> >    Generic routine to setup the PCI features as per its predetermined defaults.
> >  **/
> > @@ -364,6 +421,7 @@ SetupDefaultsDevicePlatformPolicy (
> >    IN  PCI_IO_DEVICE               *PciDevice
> >    )
> >  {
> > +  PciDevice->SetupMPS = EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO;
> >  }
> >
> >  /**
> > @@ -399,6 +457,7 @@ GetPciDevicePlatformPolicyEx (
> >        //
> >        // platform chipset policies are returned for this PCI device
> >        //
> > +      PciIoDevice->SetupMPS = PciPlatformExtendedPolicy.DeviceCtlMPS;
> >
> >        DEBUG ((
> >            DEBUG_INFO, "[device policy: platform]"
> > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > index a13131c..786c00d 100644
> > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > @@ -124,4 +124,36 @@ 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
> > +);
> > +
> > +/**
> > +  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
> > +);
> >  #endif
> > --
> > 2.21.0.windows.1
> >
> >
> > 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12] PciBusDxe: New PCI feature Max_Payload_Size
  2019-12-18  8:38     ` Ni, Ray
@ 2019-12-18  9:10       ` Ni, Ray
  2019-12-18 14:35         ` Javeed, Ashraf
  0 siblings, 1 reply; 51+ messages in thread
From: Ni, Ray @ 2019-12-18  9:10 UTC (permalink / raw)
  To: Javeed, Ashraf, 'devel@edk2.groups.io'; +Cc: Wang, Jian J, Wu, Hao A

Ashraf,
Can ProcessMaxPayloadSize() get the minimum payload size for all devices under a certain root port?

I can understand that the payload size stored in the PCI features configuration table is the minimum value.
But the value stored in each PciDevice->SetupMPS is not the minimum value.

So OverrideMaxPayloadSize() should use the value stored in the PCI features configuration table instead of the value stored in PciDevice->SetupMPS.

Thanks,
Ray

> -----Original Message-----
> From: Ni, Ray
> Sent: Wednesday, December 18, 2019 4:38 PM
> To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12] PciBusDxe: New PCI feature Max_Payload_Size
> 
> > > +  UINT8                                     SetupMPS;
> 1. Can it be "MaxPayloadSize"?
> > > +
> > > +  if (PciConfigPhase == PciFeatureGetDevicePolicy) {
> > > +    if (SetupMpsAsPerDeviceCapability (PciDevice->SetupMPS)) {
> 
> 2. Can you replace " SetupMpsAsPerDeviceCapability (PciDevice->SetupMPS" with
> "PciDevice->MaxPayloadSize == EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO"?
> This makes the code more readable.
> 
> > > +      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;
> > > +        }
> > > +      }
> 
> 3. Above two if-s can be simplified as below? and please also copy the spec requirements here as comments.
> if (IsListEmpty (&PciDevice->ChildList)) {
>   MpsValue = PCIE_MAX_PAYLOAD_SIZE_128B;
> }
> 
> 
> 
> > > +    } else {
> > > +      MpsValue = TranslateMpsSetupValueToPci (PciDevice->SetupMPS);
> 
> 4. The function name can be "UefiToPciMaxPayloadSize()". And I suggest the
> value stored in PciDevice->SetupMPS (MaxPayloadSize) is the macro value
> defined in PciExpress21.h. We could do the conversion just after the GetDevicePolicy() call.
> 
> > > +    }
> > > +    //
> > > +    // 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;
> 
> 5. Max_Payload_Size can be "MaxPayloadSize".
> MpsValue can be "MaxPayloadSize".
> 
> > > +
> > > +    MpsValue = MIN (PciDevice->SetupMPS, MpsValue);
> > > +    PciDevice->SetupMPS = MIN (PciDevice->SetupMPS, MpsValue);
> > > +
> > > +    if (MpsValue != PciFeaturesConfigurationTable->Max_Payload_Size) {
> > > +      PciFeaturesConfigurationTable->Max_Payload_Size = MpsValue;
> > > +    }
> > > +  }
> 
> 6. Can you simplify the above logic?
> 
> > > +
> > > +  DEBUG (( DEBUG_INFO,
> > > +      "MPS: %d [DevCap:%d],",
> > > +      PciDevice->SetupMPS, PciDeviceCap.Bits.MaxPayloadSize
> > > +  ));
> > > +  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
> > > +  )
> 
> 7. Can this name be "ProgramMaxPayloadSize" because the function does
> the register programming?
> 
> > > +{
> > > +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> > > +  UINT32                      Offset;
> > > +  EFI_STATUS                  Status;
> > > +  EFI_TPL                     OldTpl;
> > > +
> > > +  PcieDev.Uint16 = 0;
> > > +  Offset = PciDevice->PciExpressCapabilityOffset +
> > > +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> > > + Status = PciDevice->PciIo.Pci.Read (
> > > +                                  &PciDevice->PciIo,
> > > +                                  EfiPciIoWidthUint16,
> > > +                                  Offset,
> > > +                                  1,
> > > +                                  &PcieDev.Uint16
> > > +                                );
> 
> 8. The PciExp is cached in PciExp field in the PciDevice structure. Why do you need
> to read it from HW again?
> 
> > > +  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, "MPS=%d,", PciDevice->SetupMPS));
> > > +
> > > +    //
> > > +    // Raise TPL to high level to disable timer interrupt while the write operation
> > > completes
> > > +    //
> > > +    OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
> > > +
> > > +    Status = PciDevice->PciIo.Pci.Write (
> > > +                                    &PciDevice->PciIo,
> > > +                                    EfiPciIoWidthUint16,
> > > +                                    Offset,
> > > +                                    1,
> > > +                                    &PcieDev.Uint16
> > > +                                  );
> > > +    //
> > > +    // Restore TPL to its original level
> > > +    //
> > > +    gBS->RestoreTPL (OldTpl);
> > > +
> > > +    if (!EFI_ERROR(Status)) {
> > > +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> > > +    } else {
> > > +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register (0x%x) write
> > > error!",
> > > +          Offset
> > > +      ));
> 
> 9. We can use ASSERT_EFI_ERROR() here. Failure of register writing is a fatal error.
> 
> > > +    }
> > > +  } else {
> > > +    DEBUG (( DEBUG_INFO, "No write of MPS=%d,", PciDevice->SetupMPS));
> 
> 10. Can we skip this debug message?
> 
> > > + }
> > > +
> > > +  return Status;
> > > +}
> > >
> > >  /**
> > >    helper routine to dump the PCIe Device Port Type @@ -669,6 +809,18 @@
> > > SetupDevicePciFeatures (
> > >      }
> > >    }
> > >
> > > +  DEBUG ((DEBUG_INFO, "["));
> > > +  //
> > > +  // process the PCI device Max_Payload_Size feature  //  if
> > > + (SetupMaxPayloadSize ()) {
> > > +    Status = ProcessMaxPayloadSize (
> > > +              PciDevice,
> > > +              PciConfigPhase,
> > > +              OtherPciFeaturesConfigTable
> > > +              );
> 
> 11. Can this function be "CalculatemaxPayloadSize"? Process is too general.
> 
> > > +  }
> > > +  DEBUG ((DEBUG_INFO, "]\n"));
> > >    return Status;
> > >  }
> > >
> > > @@ -765,6 +917,10 @@ ProgramDevicePciFeatures (  {
> > >    EFI_STATUS           Status = EFI_SUCCESS;
> > >
> > > +  if (SetupMaxPayloadSize ()) {
> > > +    Status = OverrideMaxPayloadSize (PciDevice);  }  DEBUG ((
> > > + DEBUG_INFO, "\n"));
> > >    return Status;
> > >  }
> > >
> > > @@ -878,6 +1034,7 @@ AddPrimaryRootPortNode (
> > >                      );
> > >    if (PciConfigTable) {
> > >      PciConfigTable->ID                          = PortNumber;
> > > +    PciConfigTable->Max_Payload_Size            =
> > > PCIE_MAX_PAYLOAD_SIZE_4096B;
> > >    }
> > >    RootPortNode->OtherPciFeaturesConfigurationTable  = PciConfigTable;
> > >
> > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > index f92d008..e5ac2a3 100644
> > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > @@ -79,6 +79,11 @@ 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;
> > >  };
> > >
> > >
> > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > index 238959e..99badd6 100644
> > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > @@ -356,6 +356,63 @@ GetPlatformPciOptionRom (
> > >    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;
> > > +  }
> > > +}
> > > +
> > > +/**
> > > +  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;
> > > +  }
> > > +}
> > > +
> > >  /**
> > >    Generic routine to setup the PCI features as per its predetermined defaults.
> > >  **/
> > > @@ -364,6 +421,7 @@ SetupDefaultsDevicePlatformPolicy (
> > >    IN  PCI_IO_DEVICE               *PciDevice
> > >    )
> > >  {
> > > +  PciDevice->SetupMPS = EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO;
> > >  }
> > >
> > >  /**
> > > @@ -399,6 +457,7 @@ GetPciDevicePlatformPolicyEx (
> > >        //
> > >        // platform chipset policies are returned for this PCI device
> > >        //
> > > +      PciIoDevice->SetupMPS = PciPlatformExtendedPolicy.DeviceCtlMPS;
> > >
> > >        DEBUG ((
> > >            DEBUG_INFO, "[device policy: platform]"
> > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > index a13131c..786c00d 100644
> > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > @@ -124,4 +124,36 @@ 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
> > > +);
> > > +
> > > +/**
> > > +  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
> > > +);
> > >  #endif
> > > --
> > > 2.21.0.windows.1
> > >
> > >
> > > 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12] PciBusDxe: New PCI feature Max_Payload_Size
  2019-12-18  9:10       ` Ni, Ray
@ 2019-12-18 14:35         ` Javeed, Ashraf
  2019-12-19  2:14           ` Ni, Ray
  0 siblings, 1 reply; 51+ messages in thread
From: Javeed, Ashraf @ 2019-12-18 14:35 UTC (permalink / raw)
  To: Ni, Ray, 'devel@edk2.groups.io'; +Cc: Wang, Jian J, Wu, Hao A

Ray,
As discussed, the ProcessMaxPayloadSize() gets the minimum payload size for all devices under a certain root port, at the end of PciFeatureSetupPhase.
The value from the PCI features configuration table is aligned to each of PciDevice->SetupMPS, under a root port. 
The PciDevice->SetupMPS is used for its corresponding device's MaxReadRequestSize feature conditionally, since there is no PCIe capability for this feature.
Thus, as per the implementation design formulated here, all the PciDevice->SetupXXX has to be finalized, considering the device policy, during the phases - PciFeatureGetDevicePolicy & PciFeatureSetupPhase. Finally, it shall be programmed during the phase PciFeatureConfigurationPhase.
The OverrideMaxPayloadSize() does not have to use the PCI features configuration table, as that table is temporarily meant for aligning a feature value among all devices of a root port.

Responding to your other comments below inline.
Thanks
Ashraf


> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Wednesday, December 18, 2019 2:40 PM
> To: Javeed, Ashraf <ashraf.javeed@intel.com>; 'devel@edk2.groups.io'
> <devel@edk2.groups.io>
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12]
> PciBusDxe: New PCI feature Max_Payload_Size
> 
> Ashraf,
> Can ProcessMaxPayloadSize() get the minimum payload size for all devices under
> a certain root port?
> 
> I can understand that the payload size stored in the PCI features configuration
> table is the minimum value.
> But the value stored in each PciDevice->SetupMPS is not the minimum value.
> 
> So OverrideMaxPayloadSize() should use the value stored in the PCI features
> configuration table instead of the value stored in PciDevice->SetupMPS.
> 
> Thanks,
> Ray
> 
> > -----Original Message-----
> > From: Ni, Ray
> > Sent: Wednesday, December 18, 2019 4:38 PM
> > To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > <hao.a.wu@intel.com>
> > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > 08/12] PciBusDxe: New PCI feature Max_Payload_Size
> >
> > > > +  UINT8                                     SetupMPS;
> > 1. Can it be "MaxPayloadSize"?
I thought prefixing the name with "Setup" can imply that this data member of PCI_IO_DEVICE would help to indicate it takes the device policy, transforms into the final raw value after calculation, which shall be programmed in to hardware control register. I have used same style for all other features, and I have to rename all those....I don't see any conflict in the name SetupMPS as we know that MPS is shorthand for the MaxPayLoadSize...

> > > > +
> > > > +  if (PciConfigPhase == PciFeatureGetDevicePolicy) {
> > > > +    if (SetupMpsAsPerDeviceCapability (PciDevice->SetupMPS)) {
> >
> > 2. Can you replace " SetupMpsAsPerDeviceCapability
> > (PciDevice->SetupMPS" with "PciDevice->MaxPayloadSize ==
> EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO"?
> > This makes the code more readable.
> >
I thought the routine name itself informally indicate what type of action it has to take based on *_AUTO EFI encoding....I shall reconsider this.

> > > > +      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;
> > > > +        }
> > > > +      }
> >
> > 3. Above two if-s can be simplified as below? and please also copy the spec
> requirements here as comments.
> > if (IsListEmpty (&PciDevice->ChildList)) {
> >   MpsValue = PCIE_MAX_PAYLOAD_SIZE_128B; }
> >
OK

> >
> >
> > > > +    } else {
> > > > +      MpsValue = TranslateMpsSetupValueToPci
> > > > + (PciDevice->SetupMPS);
> >
> > 4. The function name can be "UefiToPciMaxPayloadSize()". And I suggest
> > the value stored in PciDevice->SetupMPS (MaxPayloadSize) is the macro
> > value defined in PciExpress21.h. We could do the conversion just after the
> GetDevicePolicy() call.
> >
Ok, I can rename to the suggested name for the translation routine. But, I cannot use that immediately after the GetDevicePolicy() because some of the PCIe features are defined in the capability register and its *_AUTO can be used in co-relation to that; like in case of MaxPayloadSize feature; but in case of PCIe feature like RelaxOrdering & NoSnoop, the PCI Base Specification has not defined any corresponding capability or hardware reference value for look-up, thus *_AUTO for these kind of features would be to just ignore it.

> > > > +    }
> > > > +    //
> > > > +    // 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;
> >
> > 5. Max_Payload_Size can be "MaxPayloadSize".
> > MpsValue can be "MaxPayloadSize".
> >
OK

> > > > +
> > > > +    MpsValue = MIN (PciDevice->SetupMPS, MpsValue);
> > > > +    PciDevice->SetupMPS = MIN (PciDevice->SetupMPS, MpsValue);
> > > > +
> > > > +    if (MpsValue != PciFeaturesConfigurationTable->Max_Payload_Size) {
> > > > +      PciFeaturesConfigurationTable->Max_Payload_Size = MpsValue;
> > > > +    }
> > > > +  }
> >
> > 6. Can you simplify the above logic?
> >
Will check on this

> > > > +
> > > > +  DEBUG (( DEBUG_INFO,
> > > > +      "MPS: %d [DevCap:%d],",
> > > > +      PciDevice->SetupMPS, PciDeviceCap.Bits.MaxPayloadSize
> > > > +  ));
> > > > +  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
> > > > +  )
> >
> > 7. Can this name be "ProgramMaxPayloadSize" because the function does
> > the register programming?
> >
OK

> > > > +{
> > > > +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> > > > +  UINT32                      Offset;
> > > > +  EFI_STATUS                  Status;
> > > > +  EFI_TPL                     OldTpl;
> > > > +
> > > > +  PcieDev.Uint16 = 0;
> > > > +  Offset = PciDevice->PciExpressCapabilityOffset +
> > > > +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> > > > + Status = PciDevice->PciIo.Pci.Read (
> > > > +                                  &PciDevice->PciIo,
> > > > +                                  EfiPciIoWidthUint16,
> > > > +                                  Offset,
> > > > +                                  1,
> > > > +                                  &PcieDev.Uint16
> > > > +                                );
> >
> > 8. The PciExp is cached in PciExp field in the PciDevice structure.
> > Why do you need to read it from HW again?
> >
Just for the sake of defensive programming; in case platform has done some overrides in between; since numerous callbacks are going to platform code of PCI Host Bridge Resource Allocation Protocol driver,  and PCI Platform Protocol driver. 

> > > > +  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, "MPS=%d,", PciDevice->SetupMPS));
> > > > +
> > > > +    //
> > > > +    // Raise TPL to high level to disable timer interrupt while
> > > > + the write operation
> > > > completes
> > > > +    //
> > > > +    OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
> > > > +
> > > > +    Status = PciDevice->PciIo.Pci.Write (
> > > > +                                    &PciDevice->PciIo,
> > > > +                                    EfiPciIoWidthUint16,
> > > > +                                    Offset,
> > > > +                                    1,
> > > > +                                    &PcieDev.Uint16
> > > > +                                  );
> > > > +    //
> > > > +    // Restore TPL to its original level
> > > > +    //
> > > > +    gBS->RestoreTPL (OldTpl);
> > > > +
> > > > +    if (!EFI_ERROR(Status)) {
> > > > +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> > > > +    } else {
> > > > +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register
> > > > + (0x%x) write
> > > > error!",
> > > > +          Offset
> > > > +      ));
> >
> > 9. We can use ASSERT_EFI_ERROR() here. Failure of register writing is a fatal
> error.
> >
OK

> > > > +    }
> > > > +  } else {
> > > > +    DEBUG (( DEBUG_INFO, "No write of MPS=%d,",
> > > > + PciDevice->SetupMPS));
> >
> > 10. Can we skip this debug message?
> >
OK

> > > > + }
> > > > +
> > > > +  return Status;
> > > > +}
> > > >
> > > >  /**
> > > >    helper routine to dump the PCIe Device Port Type @@ -669,6
> > > > +809,18 @@ SetupDevicePciFeatures (
> > > >      }
> > > >    }
> > > >
> > > > +  DEBUG ((DEBUG_INFO, "["));
> > > > +  //
> > > > +  // process the PCI device Max_Payload_Size feature  //  if
> > > > + (SetupMaxPayloadSize ()) {
> > > > +    Status = ProcessMaxPayloadSize (
> > > > +              PciDevice,
> > > > +              PciConfigPhase,
> > > > +              OtherPciFeaturesConfigTable
> > > > +              );
> >
> > 11. Can this function be "CalculatemaxPayloadSize"? Process is too general.
> >
OK

> > > > +  }
> > > > +  DEBUG ((DEBUG_INFO, "]\n"));
> > > >    return Status;
> > > >  }
> > > >
> > > > @@ -765,6 +917,10 @@ ProgramDevicePciFeatures (  {
> > > >    EFI_STATUS           Status = EFI_SUCCESS;
> > > >
> > > > +  if (SetupMaxPayloadSize ()) {
> > > > +    Status = OverrideMaxPayloadSize (PciDevice);  }  DEBUG ((
> > > > + DEBUG_INFO, "\n"));
> > > >    return Status;
> > > >  }
> > > >
> > > > @@ -878,6 +1034,7 @@ AddPrimaryRootPortNode (
> > > >                      );
> > > >    if (PciConfigTable) {
> > > >      PciConfigTable->ID                          = PortNumber;
> > > > +    PciConfigTable->Max_Payload_Size            =
> > > > PCIE_MAX_PAYLOAD_SIZE_4096B;
> > > >    }
> > > >    RootPortNode->OtherPciFeaturesConfigurationTable  =
> > > > PciConfigTable;
> > > >
> > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > > index f92d008..e5ac2a3 100644
> > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > > @@ -79,6 +79,11 @@ 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;
> > > >  };
> > > >
> > > >
> > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > > index 238959e..99badd6 100644
> > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > > @@ -356,6 +356,63 @@ GetPlatformPciOptionRom (
> > > >    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;
> > > > +  }
> > > > +}
> > > > +
> > > > +/**
> > > > +  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;
> > > > +  }
> > > > +}
> > > > +
> > > >  /**
> > > >    Generic routine to setup the PCI features as per its predetermined
> defaults.
> > > >  **/
> > > > @@ -364,6 +421,7 @@ SetupDefaultsDevicePlatformPolicy (
> > > >    IN  PCI_IO_DEVICE               *PciDevice
> > > >    )
> > > >  {
> > > > +  PciDevice->SetupMPS = EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO;
> > > >  }
> > > >
> > > >  /**
> > > > @@ -399,6 +457,7 @@ GetPciDevicePlatformPolicyEx (
> > > >        //
> > > >        // platform chipset policies are returned for this PCI device
> > > >        //
> > > > +      PciIoDevice->SetupMPS =
> > > > + PciPlatformExtendedPolicy.DeviceCtlMPS;
> > > >
> > > >        DEBUG ((
> > > >            DEBUG_INFO, "[device policy: platform]"
> > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > > index a13131c..786c00d 100644
> > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > > @@ -124,4 +124,36 @@ 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
> > > > +);
> > > > +
> > > > +/**
> > > > +  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
> > > > +);
> > > >  #endif
> > > > --
> > > > 2.21.0.windows.1
> > > >
> > > >
> > > > 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12] PciBusDxe: Separation of the PCI device registration and start
  2019-12-17  3:19       ` Javeed, Ashraf
@ 2019-12-19  1:34         ` Ni, Ray
  2019-12-19  4:12           ` Javeed, Ashraf
  0 siblings, 1 reply; 51+ messages in thread
From: Ni, Ray @ 2019-12-19  1:34 UTC (permalink / raw)
  To: Javeed, Ashraf, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

> >
> > 2 minor comments:
> > 1. StartPciRootPortsOnBridge()
> >      Can it be renamed to EnablePciDevicesOnBridge()?
> >      Because it basically calls PciIo.Attribute() to enable the devices. And I am
> not
> > sure the enable only applies to PCI root ports. There could be PCI devices
> behind
> > P2P bridge.
> It enables only Type 1 PCI devices (Root Port, PCIe-to-PCI Bridge, PCIe switch
> upstream/downstream ports), and no endpoint (Type 0) devices.

I see. Then how about EnablePciBridges()?


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12] PciBusDxe: New PCI feature Max_Payload_Size
  2019-12-18 14:35         ` Javeed, Ashraf
@ 2019-12-19  2:14           ` Ni, Ray
  0 siblings, 0 replies; 51+ messages in thread
From: Ni, Ray @ 2019-12-19  2:14 UTC (permalink / raw)
  To: Javeed, Ashraf, 'devel@edk2.groups.io'; +Cc: Wang, Jian J, Wu, Hao A

Ashraf,
At the end of PciFeatureGetDevicePolicy, value from the PCI features configuration table is the minimum one.
I prefer to defer the finalize of PciDevice->SetupMPS in the OverrideMaxPayloadSize().
Through this, the 4 phases can be reduced to 3 phases.

Thanks,
Ray

> -----Original Message-----
> From: Javeed, Ashraf <ashraf.javeed@intel.com>
> Sent: Wednesday, December 18, 2019 10:36 PM
> To: Ni, Ray <ray.ni@intel.com>; 'devel@edk2.groups.io'
> <devel@edk2.groups.io>
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12]
> PciBusDxe: New PCI feature Max_Payload_Size
> 
> Ray,
> As discussed, the ProcessMaxPayloadSize() gets the minimum payload size
> for all devices under a certain root port, at the end of PciFeatureSetupPhase.
> The value from the PCI features configuration table is aligned to each of
> PciDevice->SetupMPS, under a root port.
> The PciDevice->SetupMPS is used for its corresponding device's
> MaxReadRequestSize feature conditionally, since there is no PCIe capability
> for this feature.
> Thus, as per the implementation design formulated here, all the PciDevice-
> >SetupXXX has to be finalized, considering the device policy, during the
> phases - PciFeatureGetDevicePolicy & PciFeatureSetupPhase. Finally, it shall
> be programmed during the phase PciFeatureConfigurationPhase.
> The OverrideMaxPayloadSize() does not have to use the PCI features
> configuration table, as that table is temporarily meant for aligning a feature
> value among all devices of a root port.
> 
> Responding to your other comments below inline.
> Thanks
> Ashraf
> 
> 
> > -----Original Message-----
> > From: Ni, Ray <ray.ni@intel.com>
> > Sent: Wednesday, December 18, 2019 2:40 PM
> > To: Javeed, Ashraf <ashraf.javeed@intel.com>; 'devel@edk2.groups.io'
> > <devel@edk2.groups.io>
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> 08/12]
> > PciBusDxe: New PCI feature Max_Payload_Size
> >
> > Ashraf,
> > Can ProcessMaxPayloadSize() get the minimum payload size for all devices
> under
> > a certain root port?
> >
> > I can understand that the payload size stored in the PCI features
> configuration
> > table is the minimum value.
> > But the value stored in each PciDevice->SetupMPS is not the minimum
> value.
> >
> > So OverrideMaxPayloadSize() should use the value stored in the PCI
> features
> > configuration table instead of the value stored in PciDevice->SetupMPS.
> >
> > Thanks,
> > Ray
> >
> > > -----Original Message-----
> > > From: Ni, Ray
> > > Sent: Wednesday, December 18, 2019 4:38 PM
> > > To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > <hao.a.wu@intel.com>
> > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > > 08/12] PciBusDxe: New PCI feature Max_Payload_Size
> > >
> > > > > +  UINT8                                     SetupMPS;
> > > 1. Can it be "MaxPayloadSize"?
> I thought prefixing the name with "Setup" can imply that this data member
> of PCI_IO_DEVICE would help to indicate it takes the device policy,
> transforms into the final raw value after calculation, which shall be
> programmed in to hardware control register. I have used same style for all
> other features, and I have to rename all those....I don't see any conflict in the
> name SetupMPS as we know that MPS is shorthand for the
> MaxPayLoadSize...
> 
> > > > > +
> > > > > +  if (PciConfigPhase == PciFeatureGetDevicePolicy) {
> > > > > +    if (SetupMpsAsPerDeviceCapability (PciDevice->SetupMPS)) {
> > >
> > > 2. Can you replace " SetupMpsAsPerDeviceCapability
> > > (PciDevice->SetupMPS" with "PciDevice->MaxPayloadSize ==
> > EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO"?
> > > This makes the code more readable.
> > >
> I thought the routine name itself informally indicate what type of action it has
> to take based on *_AUTO EFI encoding....I shall reconsider this.
> 
> > > > > +      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;
> > > > > +        }
> > > > > +      }
> > >
> > > 3. Above two if-s can be simplified as below? and please also copy the
> spec
> > requirements here as comments.
> > > if (IsListEmpty (&PciDevice->ChildList)) {
> > >   MpsValue = PCIE_MAX_PAYLOAD_SIZE_128B; }
> > >
> OK
> 
> > >
> > >
> > > > > +    } else {
> > > > > +      MpsValue = TranslateMpsSetupValueToPci
> > > > > + (PciDevice->SetupMPS);
> > >
> > > 4. The function name can be "UefiToPciMaxPayloadSize()". And I suggest
> > > the value stored in PciDevice->SetupMPS (MaxPayloadSize) is the macro
> > > value defined in PciExpress21.h. We could do the conversion just after
> the
> > GetDevicePolicy() call.
> > >
> Ok, I can rename to the suggested name for the translation routine. But, I
> cannot use that immediately after the GetDevicePolicy() because some of
> the PCIe features are defined in the capability register and its *_AUTO can be
> used in co-relation to that; like in case of MaxPayloadSize feature; but in case
> of PCIe feature like RelaxOrdering & NoSnoop, the PCI Base Specification has
> not defined any corresponding capability or hardware reference value for
> look-up, thus *_AUTO for these kind of features would be to just ignore it.
> 
> > > > > +    }
> > > > > +    //
> > > > > +    // 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;
> > >
> > > 5. Max_Payload_Size can be "MaxPayloadSize".
> > > MpsValue can be "MaxPayloadSize".
> > >
> OK
> 
> > > > > +
> > > > > +    MpsValue = MIN (PciDevice->SetupMPS, MpsValue);
> > > > > +    PciDevice->SetupMPS = MIN (PciDevice->SetupMPS, MpsValue);
> > > > > +
> > > > > +    if (MpsValue != PciFeaturesConfigurationTable-
> >Max_Payload_Size) {
> > > > > +      PciFeaturesConfigurationTable->Max_Payload_Size = MpsValue;
> > > > > +    }
> > > > > +  }
> > >
> > > 6. Can you simplify the above logic?
> > >
> Will check on this
> 
> > > > > +
> > > > > +  DEBUG (( DEBUG_INFO,
> > > > > +      "MPS: %d [DevCap:%d],",
> > > > > +      PciDevice->SetupMPS, PciDeviceCap.Bits.MaxPayloadSize
> > > > > +  ));
> > > > > +  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
> > > > > +  )
> > >
> > > 7. Can this name be "ProgramMaxPayloadSize" because the function
> does
> > > the register programming?
> > >
> OK
> 
> > > > > +{
> > > > > +  PCI_REG_PCIE_DEVICE_CONTROL PcieDev;
> > > > > +  UINT32                      Offset;
> > > > > +  EFI_STATUS                  Status;
> > > > > +  EFI_TPL                     OldTpl;
> > > > > +
> > > > > +  PcieDev.Uint16 = 0;
> > > > > +  Offset = PciDevice->PciExpressCapabilityOffset +
> > > > > +               OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl);
> > > > > + Status = PciDevice->PciIo.Pci.Read (
> > > > > +                                  &PciDevice->PciIo,
> > > > > +                                  EfiPciIoWidthUint16,
> > > > > +                                  Offset,
> > > > > +                                  1,
> > > > > +                                  &PcieDev.Uint16
> > > > > +                                );
> > >
> > > 8. The PciExp is cached in PciExp field in the PciDevice structure.
> > > Why do you need to read it from HW again?
> > >
> Just for the sake of defensive programming; in case platform has done some
> overrides in between; since numerous callbacks are going to platform code
> of PCI Host Bridge Resource Allocation Protocol driver,  and PCI Platform
> Protocol driver.
> 
> > > > > +  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, "MPS=%d,", PciDevice->SetupMPS));
> > > > > +
> > > > > +    //
> > > > > +    // Raise TPL to high level to disable timer interrupt while
> > > > > + the write operation
> > > > > completes
> > > > > +    //
> > > > > +    OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
> > > > > +
> > > > > +    Status = PciDevice->PciIo.Pci.Write (
> > > > > +                                    &PciDevice->PciIo,
> > > > > +                                    EfiPciIoWidthUint16,
> > > > > +                                    Offset,
> > > > > +                                    1,
> > > > > +                                    &PcieDev.Uint16
> > > > > +                                  );
> > > > > +    //
> > > > > +    // Restore TPL to its original level
> > > > > +    //
> > > > > +    gBS->RestoreTPL (OldTpl);
> > > > > +
> > > > > +    if (!EFI_ERROR(Status)) {
> > > > > +      PciDevice->PciExpStruct.DeviceControl.Uint16 = PcieDev.Uint16;
> > > > > +    } else {
> > > > > +      DEBUG (( DEBUG_ERROR, "Unexpected DeviceControl register
> > > > > + (0x%x) write
> > > > > error!",
> > > > > +          Offset
> > > > > +      ));
> > >
> > > 9. We can use ASSERT_EFI_ERROR() here. Failure of register writing is a
> fatal
> > error.
> > >
> OK
> 
> > > > > +    }
> > > > > +  } else {
> > > > > +    DEBUG (( DEBUG_INFO, "No write of MPS=%d,",
> > > > > + PciDevice->SetupMPS));
> > >
> > > 10. Can we skip this debug message?
> > >
> OK
> 
> > > > > + }
> > > > > +
> > > > > +  return Status;
> > > > > +}
> > > > >
> > > > >  /**
> > > > >    helper routine to dump the PCIe Device Port Type @@ -669,6
> > > > > +809,18 @@ SetupDevicePciFeatures (
> > > > >      }
> > > > >    }
> > > > >
> > > > > +  DEBUG ((DEBUG_INFO, "["));
> > > > > +  //
> > > > > +  // process the PCI device Max_Payload_Size feature  //  if
> > > > > + (SetupMaxPayloadSize ()) {
> > > > > +    Status = ProcessMaxPayloadSize (
> > > > > +              PciDevice,
> > > > > +              PciConfigPhase,
> > > > > +              OtherPciFeaturesConfigTable
> > > > > +              );
> > >
> > > 11. Can this function be "CalculatemaxPayloadSize"? Process is too
> general.
> > >
> OK
> 
> > > > > +  }
> > > > > +  DEBUG ((DEBUG_INFO, "]\n"));
> > > > >    return Status;
> > > > >  }
> > > > >
> > > > > @@ -765,6 +917,10 @@ ProgramDevicePciFeatures (  {
> > > > >    EFI_STATUS           Status = EFI_SUCCESS;
> > > > >
> > > > > +  if (SetupMaxPayloadSize ()) {
> > > > > +    Status = OverrideMaxPayloadSize (PciDevice);  }  DEBUG ((
> > > > > + DEBUG_INFO, "\n"));
> > > > >    return Status;
> > > > >  }
> > > > >
> > > > > @@ -878,6 +1034,7 @@ AddPrimaryRootPortNode (
> > > > >                      );
> > > > >    if (PciConfigTable) {
> > > > >      PciConfigTable->ID                          = PortNumber;
> > > > > +    PciConfigTable->Max_Payload_Size            =
> > > > > PCIE_MAX_PAYLOAD_SIZE_4096B;
> > > > >    }
> > > > >    RootPortNode->OtherPciFeaturesConfigurationTable  =
> > > > > PciConfigTable;
> > > > >
> > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > > > index f92d008..e5ac2a3 100644
> > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
> > > > > @@ -79,6 +79,11 @@ 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;
> > > > >  };
> > > > >
> > > > >
> > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > > > index 238959e..99badd6 100644
> > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
> > > > > @@ -356,6 +356,63 @@ GetPlatformPciOptionRom (
> > > > >    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;
> > > > > +  }
> > > > > +}
> > > > > +
> > > > > +/**
> > > > > +  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;
> > > > > +  }
> > > > > +}
> > > > > +
> > > > >  /**
> > > > >    Generic routine to setup the PCI features as per its predetermined
> > defaults.
> > > > >  **/
> > > > > @@ -364,6 +421,7 @@ SetupDefaultsDevicePlatformPolicy (
> > > > >    IN  PCI_IO_DEVICE               *PciDevice
> > > > >    )
> > > > >  {
> > > > > +  PciDevice->SetupMPS =
> EFI_PCI_CONF_MAX_PAYLOAD_SIZE_AUTO;
> > > > >  }
> > > > >
> > > > >  /**
> > > > > @@ -399,6 +457,7 @@ GetPciDevicePlatformPolicyEx (
> > > > >        //
> > > > >        // platform chipset policies are returned for this PCI device
> > > > >        //
> > > > > +      PciIoDevice->SetupMPS =
> > > > > + PciPlatformExtendedPolicy.DeviceCtlMPS;
> > > > >
> > > > >        DEBUG ((
> > > > >            DEBUG_INFO, "[device policy: platform]"
> > > > > diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > > > b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > > > index a13131c..786c00d 100644
> > > > > --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > > > +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h
> > > > > @@ -124,4 +124,36 @@ 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
> > > > > +);
> > > > > +
> > > > > +/**
> > > > > +  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
> > > > > +);
> > > > >  #endif
> > > > > --
> > > > > 2.21.0.windows.1
> > > > >
> > > > >
> > > > > 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12] PciBusDxe: Separation of the PCI device registration and start
  2019-12-19  1:34         ` Ni, Ray
@ 2019-12-19  4:12           ` Javeed, Ashraf
  0 siblings, 0 replies; 51+ messages in thread
From: Javeed, Ashraf @ 2019-12-19  4:12 UTC (permalink / raw)
  To: Ni, Ray, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A



> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Thursday, December 19, 2019 7:04 AM
> To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12]
> PciBusDxe: Separation of the PCI device registration and start
> 
> > >
> > > 2 minor comments:
> > > 1. StartPciRootPortsOnBridge()
> > >      Can it be renamed to EnablePciDevicesOnBridge()?
> > >      Because it basically calls PciIo.Attribute() to enable the
> > > devices. And I am
> > not
> > > sure the enable only applies to PCI root ports. There could be PCI
> > > devices
> > behind
> > > P2P bridge.
> > It enables only Type 1 PCI devices (Root Port, PCIe-to-PCI Bridge,
> > PCIe switch upstream/downstream ports), and no endpoint (Type 0) devices.
> 
> I see. Then how about EnablePciBridges()?
This will do.


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
  2019-12-18  7:14       ` Javeed, Ashraf
@ 2019-12-19  5:48         ` Ni, Ray
       [not found]         ` <15E1AFB3EABD031C.30484@groups.io>
  1 sibling, 0 replies; 51+ messages in thread
From: Ni, Ray @ 2019-12-19  5:48 UTC (permalink / raw)
  To: Javeed, Ashraf, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

After I reviewed the patch of enabling MaxPayloadSize, MaxReadReqSize and more PCIE features,
I can now understand the phases more than earlier.

Your patch proposed five phases:
  //
  // 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


I have several comments to the five phases.
1. Scan phase is not do the scanning but creates a list to hold all root ports under
the root bridge.
2. Root ports collection is not required by all of the features, only by MPS and MRRS.
But the collection always happens even when platform doesn't require PciBus to initialize
MPS or MRRS.
3. GetDevicePolicy phase is not just call the GetDevicePolicy for each device. It also reads
the PCIE configuration space to get the device's feature related capabilities, for some of the
features.

With that, I propose to define 4 phases:
1. Initialize phase
This phase is similar to your Scan phase.
For some features, this phase does nothing.
For MPS and MRRS, this phase creates a list holding all root ports.

2. Scan phase
This phase is similar to your GetDevicePolicy phase.
For some features, this phase needs nothing do to.
For MPS and MRRS, this phase scan all devices and get the aligned value of MPS or MRRS.

3. Program phase or Configuration phase
This phase is similar to your Configuration phase.
The Setup phase can be merged to this phase.

4. Finalize phase.
This phase is similar to your ConfigurationComplete phase.
This phase frees the resources occupied/allocated in Initialize phase.
For some of the features, this phase may do nothing.

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

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

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

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


> -----Original Message-----
> From: Javeed, Ashraf <ashraf.javeed@intel.com>
> Sent: Wednesday, December 18, 2019 3:14 PM
> To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12]
> PciBusDxe: Setup sub-phases for PCI feature enumeration
> 
> Thanks for the review, Ray!
> My response in line
> 
> > -----Original Message-----
> > From: Ni, Ray <ray.ni@intel.com>
> > Sent: Tuesday, December 17, 2019 5:26 PM
> > To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> 05/12]
> > PciBusDxe: Setup sub-phases for PCI feature enumeration
> >
> > Please check comments below.
> > I may have more comments regarding to the four phases after I finish
> review of
> > further patches.
> >
> > Besides the comments below, I have a general comments to the debug
> > message: can you please review the existing debug message in the PciBus
> driver
> > and make sure your newly added debug message aligns to existing style.
> And try
> > to use less lines of debug messages with still enough debug information.
> Ok, will look into that.
> 
> >
> > > > +PRIMARY_ROOT_PORT_NODE                      *mPrimaryRootPortList;
> > > > +
> > > > +/**
> > > > +  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;
> >
> > 1. Please follow existing linked list usage style. The first node in the list is an
> > empty header node.
> >
> > LIST_ENTRY   mPrimaryRootPortList;
> > LIST_ENTRY   mPciFeaturesConfigurationCompletionList;
> >
> Ok, will make the change when I incorporate the ECR 0.75 or greater version.
> 
> > > > +BOOLEAN
> > > > +CheckPciFeatureConfigurationRecordExist (
> > > > +  IN  PCI_IO_DEVICE                             *RootBridge,
> > > > +  OUT PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > +**PciFeatureConfigRecord
> > > > +  )
> >
> > 2. Is this function to check whether the PCIE features under a root bridge is
> > already initialized?
> > Can you use the existing variable gFullEnumeration?
> > The variable is set to TRUE when the enumeration is done to a host bridge
> in the
> > first time.
> > By using gFullEnumeration, the entire function is not needed.
> >
> Ok, will look into this.
> 
> > > > +EFI_STATUS AddRootBridgeInPciFeaturesConfigCompletionList (
> > > > +  IN PCI_IO_DEVICE          *RootBridge,
> > > > +  IN BOOLEAN                ReEnumerationRequired
> > > > +  )
> >
> > 3. Same question as #2. I think by using gFullEnumeration, this function is
> not
> > needed.
> >
> OK
> 
> >
> > > > +BOOLEAN
> > > > +IsPciRootPortEmpty (
> > > > +  IN  PCI_IO_DEVICE                           *PciDevice
> > > > +  )
> >
> > 4. Please use IsListEmpty() directly from callers and remove this function.
> >
> Will consider this.
> 
> > > > +**/
> > > > +EFI_STATUS
> > > > +EnumerateOtherPciFeatures (
> >
> > 5. Can it be "EnumeratePcieFeatures"?
> >
> Yes, with the change to ECR 0.75, this routine name shall be changed.
> 
> > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > +  )
> > > > +{
> > > > +  EFI_STATUS            Status;
> > > > +  UINTN                 OtherPciFeatureConfigPhase;
> > > > +
> > > > +  //
> > > > +  // check on PCI features configuration is complete and
> > > > + re-enumeration is required  //  if
> > > > + (!CheckPciFeaturesConfigurationRequired
> > > > + (RootBridge)) {
> > > > +    return EFI_ALREADY_STARTED;
> > > > +  }
> > > > +
> >  > > +  CHAR16                *Str;
> > > > +  Str = ConvertDevicePathToText (
> > > > +          DevicePathFromHandle (RootBridge->Handle),
> > > > +          FALSE,
> > > > +          FALSE
> > > > +        );
> > > > +  DEBUG ((DEBUG_INFO, "Enumerating PCI features for Root Bridge
> > > > + %s\n", Str != NULL ? Str : L""));
> >
> > 6. Please use DEBUG_CODE macro to include ConvertDevicePathToText()
> and
> > DEBUG().
> > Please remember to call FreePool().
> >
> Ok, will can under DEBUG_CODE, and free pool is called in the end
> 
> > > > +
> > > > +  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);
> >
> > 7. How about "RecordPciRootPorts (RootBridge)"? The "Bridges" suffix is a
> bit
> > confusing.
> >
> Fine, will change.
> 
> > > > +      case  PciFeatureGetDevicePolicy:
> > > > +      case  PciFeatureSetupPhase:
> >
> > 8. In SetupPciFeatures(), why do you need to call DeviceExist()?
> > Did you see any case that a device is detected in the beginning of PciBus
> scan
> > but is hidden when calling SetupPciFeatures()?
> >
> Yes, that is the case; device detected during the beginning of PciBus scan
> appears to be hidden by the platform drivers, since numerous legacy
> callbacks are initiated at different phase of PCI enumeration to the PCI Host
> Bridge, and PciPlatform drivers.
> This can be avoided if the PciBus driver is enhanced to check for PCI device
> existence before the publication of the PCI IO Protocol, and removal of the
> PCI_IO_DEVICE instance from the linked list.
> 
> > 9. In GetPciFeaturesConfigurationTable() when checking whether a PCI
> device
> > belongs to a root port, we can use below simpler logic:
> >   SizeOfPciDevicePath = GetDevicePathSize (PciDevicePath);
> >   SizeOfRootPortDevicePath = GetDevicePathSize (RootPortPath);
> >   if ((SizeOfRootPortDevicePath < SizeOfPciDevicePath) &&
> >       CompareMem (PciDevicePath, RootPortPath,
> SizeOfRootPortDevicePath -
> > END_DEVICE_PATH_LENGTH) == 0)) {
> >     // PCI device belongs to the root port.
> >   }
> >
> Ok.
> 
> > > > +        Status = ProgramPciFeatures (RootBridge);
> > 10. ProgramPcieFeatures()?
> >
> OK
> 
> > > > +
> > > > +  if (Str != NULL) {
> > > > +    FreePool (Str);
> > > > +  }
> >
> > 11. OK the Str is freed here because Str is needed for other debug
> messages
> > inside the function.
> >
> Yes
> 
> > > > +  //
> > > > +  // mark this root bridge as PCI features configuration complete,
> > > > +and no new
> > > > +  // enumeration is required
> > > > +  //
> > > > +  AddRootBridgeInPciFeaturesConfigCompletionList (RootBridge,
> > > > +FALSE);
> >
> > 12. Not needed.
> >
> ok, after incorporating the logic of gFullEnumeration it won't be required
> 
> > > > +_PRIMARY_ROOT_PORT_NODE {
> >
> > > > +  //
> > > > +  // Signature header
> > > > +  //
> > > > +  UINT32                                    Signature;
> > > > +  //
> > > > +  // linked list pointers to next node
> > > > +  //
> > > > +  LIST_ENTRY                                NeighborRootPort;
> > > > +  //
> > > > +  // pointer to PCI_IO_DEVICE of the primary PCI Controller device
> > > > +  //
> > > > +  EFI_DEVICE_PATH_PROTOCOL                  *RootPortDevicePath;
> > > > +  //
> > > > +  // pointer to the corresponding PCI feature configuration Table
> > > > +node
> > > > +  // all the child PCI devices of the controller are aligned based
> > > > +on this table
> > > > +  //
> > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > *OtherPciFeaturesConfigurationTable;
> > > > +};
> >
> > 13. Can you add the OTHER_PCI_FEATURES_CONFIGURATION_TABLE field
> to
> > PCI_IO_DEVICE structure?
> > So this structure PRIMARY_ROOT_PORT_NODE is not needed.
> >
> I think it is better to maintain separately as this configuration table is confined
> to a group of PCI devices and for the RCiEP it is not applicable hence not
> required. Moreover, I am maintaining a variable for each PCIe feature in the
> PCI_IO_DEVICE; perhaps I can consider having just pointer of it....
> 
> > > > +struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
> > 14. This structure is not needed if using gFullEnumeration.
> Yes.

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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
       [not found]         ` <15E1AFB3EABD031C.30484@groups.io>
@ 2020-03-05 14:12           ` Ni, Ray
  2020-03-16  9:33             ` Javeed, Ashraf
  0 siblings, 1 reply; 51+ messages in thread
From: Ni, Ray @ 2020-03-05 14:12 UTC (permalink / raw)
  To: devel@edk2.groups.io, Ni, Ray, Javeed, Ashraf; +Cc: Wang, Jian J, Wu, Hao A

Ashraf,
I think it might be better to describe my review comments with code implementation.
Can you please check this branch where I did some modification based on your code?
https://github.com/niruiyu/edk2/tree/pci/pcie2

Let's firstly align on the feature initialization framework implementation.
To be specific, this commit:
MdeModulePkg/PciBus: Add the framework to init PCIE features
https://github.com/niruiyu/edk2/commit/9fb9a3dcef06de98a76825e2fc07167446ee6fd9

Thanks,
Ray

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Ni, Ray
> Sent: Thursday, December 19, 2019 1:49 PM
> To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12]
> PciBusDxe: Setup sub-phases for PCI feature enumeration
> 
> After I reviewed the patch of enabling MaxPayloadSize, MaxReadReqSize and
> more PCIE features,
> I can now understand the phases more than earlier.
> 
> Your patch proposed five phases:
>   //
>   // 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
> 
> 
> I have several comments to the five phases.
> 1. Scan phase is not do the scanning but creates a list to hold all root ports under
> the root bridge.
> 2. Root ports collection is not required by all of the features, only by MPS and
> MRRS.
> But the collection always happens even when platform doesn't require PciBus to
> initialize
> MPS or MRRS.
> 3. GetDevicePolicy phase is not just call the GetDevicePolicy for each device. It
> also reads
> the PCIE configuration space to get the device's feature related capabilities, for
> some of the
> features.
> 
> With that, I propose to define 4 phases:
> 1. Initialize phase
> This phase is similar to your Scan phase.
> For some features, this phase does nothing.
> For MPS and MRRS, this phase creates a list holding all root ports.
> 
> 2. Scan phase
> This phase is similar to your GetDevicePolicy phase.
> For some features, this phase needs nothing do to.
> For MPS and MRRS, this phase scan all devices and get the aligned value of MPS
> or MRRS.
> 
> 3. Program phase or Configuration phase
> This phase is similar to your Configuration phase.
> The Setup phase can be merged to this phase.
> 
> 4. Finalize phase.
> This phase is similar to your ConfigurationComplete phase.
> This phase frees the resources occupied/allocated in Initialize phase.
> For some of the features, this phase may do nothing.
> 
> Each feature needs to provide function pointers for each phase and NULL means
> the feature doesn't
> need to do anything in the specific phase.
> With that, we can define a structure:
> Typedef struct {
>   BOOLEAN                          Enable;
>   PCIE_FEATURE_INITILAIZE Initialize;
>   PCIE_FEATURE_SCAN  Scan;
>   PCIE_FEATURE_PROGRAM Program;
>   PCIE_FEATURE_FINALIZE Finalize;
> } PCIE_FEATURE_ENTRY;
> 
> With that, we can define a module level global variable:
> PCIE_FEATURE_ENTRY mPcieFeatures[] = {
>   { TRUE, MaxPayloadInitialize, MaxPayloadScan, MaxPayloadProgram,
> MaxPayloadFinalize},
>   { TRUE, MaxReadRequestInitialize, MaxReadRequestScan,
> MaxReadRequestProgram, MaxReadRequestFinalize},
>   { TRUE, NULL, NULL, RelaxOrderProgram, NULL},
>   { TRUE, NULL, CompletionTimeoutScan, CompletionTimeoutProgram, NULL },
>   ...
> };
> 
> PCIE_FEATURE_ENTRY.Enable can be set to FALSE according to the platform
> policy.
> 
> The enable of PCIE features can be written as a feature agnostic for-loop.
> This can make the new feature enabling code easy to add and review.
> 
> 
> > -----Original Message-----
> > From: Javeed, Ashraf <ashraf.javeed@intel.com>
> > Sent: Wednesday, December 18, 2019 3:14 PM
> > To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12]
> > PciBusDxe: Setup sub-phases for PCI feature enumeration
> >
> > Thanks for the review, Ray!
> > My response in line
> >
> > > -----Original Message-----
> > > From: Ni, Ray <ray.ni@intel.com>
> > > Sent: Tuesday, December 17, 2019 5:26 PM
> > > To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > 05/12]
> > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > >
> > > Please check comments below.
> > > I may have more comments regarding to the four phases after I finish
> > review of
> > > further patches.
> > >
> > > Besides the comments below, I have a general comments to the debug
> > > message: can you please review the existing debug message in the PciBus
> > driver
> > > and make sure your newly added debug message aligns to existing style.
> > And try
> > > to use less lines of debug messages with still enough debug information.
> > Ok, will look into that.
> >
> > >
> > > > > +PRIMARY_ROOT_PORT_NODE                      *mPrimaryRootPortList;
> > > > > +
> > > > > +/**
> > > > > +  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;
> > >
> > > 1. Please follow existing linked list usage style. The first node in the list is an
> > > empty header node.
> > >
> > > LIST_ENTRY   mPrimaryRootPortList;
> > > LIST_ENTRY   mPciFeaturesConfigurationCompletionList;
> > >
> > Ok, will make the change when I incorporate the ECR 0.75 or greater version.
> >
> > > > > +BOOLEAN
> > > > > +CheckPciFeatureConfigurationRecordExist (
> > > > > +  IN  PCI_IO_DEVICE                             *RootBridge,
> > > > > +  OUT PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > > +**PciFeatureConfigRecord
> > > > > +  )
> > >
> > > 2. Is this function to check whether the PCIE features under a root bridge is
> > > already initialized?
> > > Can you use the existing variable gFullEnumeration?
> > > The variable is set to TRUE when the enumeration is done to a host bridge
> > in the
> > > first time.
> > > By using gFullEnumeration, the entire function is not needed.
> > >
> > Ok, will look into this.
> >
> > > > > +EFI_STATUS AddRootBridgeInPciFeaturesConfigCompletionList (
> > > > > +  IN PCI_IO_DEVICE          *RootBridge,
> > > > > +  IN BOOLEAN                ReEnumerationRequired
> > > > > +  )
> > >
> > > 3. Same question as #2. I think by using gFullEnumeration, this function is
> > not
> > > needed.
> > >
> > OK
> >
> > >
> > > > > +BOOLEAN
> > > > > +IsPciRootPortEmpty (
> > > > > +  IN  PCI_IO_DEVICE                           *PciDevice
> > > > > +  )
> > >
> > > 4. Please use IsListEmpty() directly from callers and remove this function.
> > >
> > Will consider this.
> >
> > > > > +**/
> > > > > +EFI_STATUS
> > > > > +EnumerateOtherPciFeatures (
> > >
> > > 5. Can it be "EnumeratePcieFeatures"?
> > >
> > Yes, with the change to ECR 0.75, this routine name shall be changed.
> >
> > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > > +  )
> > > > > +{
> > > > > +  EFI_STATUS            Status;
> > > > > +  UINTN                 OtherPciFeatureConfigPhase;
> > > > > +
> > > > > +  //
> > > > > +  // check on PCI features configuration is complete and
> > > > > + re-enumeration is required  //  if
> > > > > + (!CheckPciFeaturesConfigurationRequired
> > > > > + (RootBridge)) {
> > > > > +    return EFI_ALREADY_STARTED;
> > > > > +  }
> > > > > +
> > >  > > +  CHAR16                *Str;
> > > > > +  Str = ConvertDevicePathToText (
> > > > > +          DevicePathFromHandle (RootBridge->Handle),
> > > > > +          FALSE,
> > > > > +          FALSE
> > > > > +        );
> > > > > +  DEBUG ((DEBUG_INFO, "Enumerating PCI features for Root Bridge
> > > > > + %s\n", Str != NULL ? Str : L""));
> > >
> > > 6. Please use DEBUG_CODE macro to include ConvertDevicePathToText()
> > and
> > > DEBUG().
> > > Please remember to call FreePool().
> > >
> > Ok, will can under DEBUG_CODE, and free pool is called in the end
> >
> > > > > +
> > > > > +  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);
> > >
> > > 7. How about "RecordPciRootPorts (RootBridge)"? The "Bridges" suffix is a
> > bit
> > > confusing.
> > >
> > Fine, will change.
> >
> > > > > +      case  PciFeatureGetDevicePolicy:
> > > > > +      case  PciFeatureSetupPhase:
> > >
> > > 8. In SetupPciFeatures(), why do you need to call DeviceExist()?
> > > Did you see any case that a device is detected in the beginning of PciBus
> > scan
> > > but is hidden when calling SetupPciFeatures()?
> > >
> > Yes, that is the case; device detected during the beginning of PciBus scan
> > appears to be hidden by the platform drivers, since numerous legacy
> > callbacks are initiated at different phase of PCI enumeration to the PCI Host
> > Bridge, and PciPlatform drivers.
> > This can be avoided if the PciBus driver is enhanced to check for PCI device
> > existence before the publication of the PCI IO Protocol, and removal of the
> > PCI_IO_DEVICE instance from the linked list.
> >
> > > 9. In GetPciFeaturesConfigurationTable() when checking whether a PCI
> > device
> > > belongs to a root port, we can use below simpler logic:
> > >   SizeOfPciDevicePath = GetDevicePathSize (PciDevicePath);
> > >   SizeOfRootPortDevicePath = GetDevicePathSize (RootPortPath);
> > >   if ((SizeOfRootPortDevicePath < SizeOfPciDevicePath) &&
> > >       CompareMem (PciDevicePath, RootPortPath,
> > SizeOfRootPortDevicePath -
> > > END_DEVICE_PATH_LENGTH) == 0)) {
> > >     // PCI device belongs to the root port.
> > >   }
> > >
> > Ok.
> >
> > > > > +        Status = ProgramPciFeatures (RootBridge);
> > > 10. ProgramPcieFeatures()?
> > >
> > OK
> >
> > > > > +
> > > > > +  if (Str != NULL) {
> > > > > +    FreePool (Str);
> > > > > +  }
> > >
> > > 11. OK the Str is freed here because Str is needed for other debug
> > messages
> > > inside the function.
> > >
> > Yes
> >
> > > > > +  //
> > > > > +  // mark this root bridge as PCI features configuration complete,
> > > > > +and no new
> > > > > +  // enumeration is required
> > > > > +  //
> > > > > +  AddRootBridgeInPciFeaturesConfigCompletionList (RootBridge,
> > > > > +FALSE);
> > >
> > > 12. Not needed.
> > >
> > ok, after incorporating the logic of gFullEnumeration it won't be required
> >
> > > > > +_PRIMARY_ROOT_PORT_NODE {
> > >
> > > > > +  //
> > > > > +  // Signature header
> > > > > +  //
> > > > > +  UINT32                                    Signature;
> > > > > +  //
> > > > > +  // linked list pointers to next node
> > > > > +  //
> > > > > +  LIST_ENTRY                                NeighborRootPort;
> > > > > +  //
> > > > > +  // pointer to PCI_IO_DEVICE of the primary PCI Controller device
> > > > > +  //
> > > > > +  EFI_DEVICE_PATH_PROTOCOL                  *RootPortDevicePath;
> > > > > +  //
> > > > > +  // pointer to the corresponding PCI feature configuration Table
> > > > > +node
> > > > > +  // all the child PCI devices of the controller are aligned based
> > > > > +on this table
> > > > > +  //
> > > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > *OtherPciFeaturesConfigurationTable;
> > > > > +};
> > >
> > > 13. Can you add the OTHER_PCI_FEATURES_CONFIGURATION_TABLE field
> > to
> > > PCI_IO_DEVICE structure?
> > > So this structure PRIMARY_ROOT_PORT_NODE is not needed.
> > >
> > I think it is better to maintain separately as this configuration table is confined
> > to a group of PCI devices and for the RCiEP it is not applicable hence not
> > required. Moreover, I am maintaining a variable for each PCIe feature in the
> > PCI_IO_DEVICE; perhaps I can consider having just pointer of it....
> >
> > > > > +struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
> > > 14. This structure is not needed if using gFullEnumeration.
> > Yes.
> 
> 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
  2020-03-05 14:12           ` Ni, Ray
@ 2020-03-16  9:33             ` Javeed, Ashraf
  2020-03-16 14:00               ` Ni, Ray
  0 siblings, 1 reply; 51+ messages in thread
From: Javeed, Ashraf @ 2020-03-16  9:33 UTC (permalink / raw)
  To: Ni, Ray, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

Ray,
First of all, thank you for taking time to review and on optimizing the PCIe feature support in the PciBusDxe.

I shall not discuss everything in detail here, just want to bring two major points:-

(1)  commit:- MdePkg: New PCI Express Platform/Override Protocols
https://github.com/niruiyu/edk2/commit/52524e9654704a7f6a30ca446f215b81fe8f0984
PCI Express Protocol not as per the ECR draft revision 0.8, the changes made has to be reviewed with updated ECR version...
the global auto option introduces EFI_PCI_EXPRESS_DEVICE_POLICY_AUTO; is used for MPS, MRRS, RO, NS, AtomicOp, LTR, results in no EFI encodings required for these 
features, as it can be used with actual values from the PciXX.h definitions. This do result in lot of code savings. 

(2) commit:- MdeModulePkg/PciBus: Add the framework to init PCIE features
https://github.com/niruiyu/edk2/commit/9fb9a3dcef06de98a76825e2fc07167446ee6fd9
The context handling of the PCIe feature MPS has fundamental issue as it is set to be common for all the nodes of the parent  Root Bridge instance. The context has to be separate to each first level nodes of a root bridge instance. For example, a root bridge has 1 RCiEP and two Root ports, than there has to be 3 separate context for each. Since Root port can have its Endpoint device, or it can have a PCIe switch with 1 upstream and 2 or more downstream ports and to each downstream port an Endpoint device can be connected; the context created for Root Port of an bridge is used for all its child hierarchy nodes; thus PCIe feature like Max_Payload_Size value can be specific to each RCiEP, and each Root ports of the Root Bridge handle. How do you propose to maintain separate context for just first level nodes of the Root Bridge handle?

The EnumeratePcieDevices() is recursively calls itself for every PCI node with a level advanced by 1. Thus, the usage of level N and N+1 as parent and its child is wrong to me, when you have a PCIe switch below the Root Port, and N & N+1 will not be direct relation between the upstream port and its second downstream port...any reason why you have not used the PCI_IO_DEVICE.Parent pointer to form relation between the parent and the child?

I liked the Pre & Post order flag that is used to processing parent-to-child vs. child-to-parent nodes. You are calling the first and last features as fakes, when you actually parse all the nodes for the GetDevicePolicy() and NotifyDeviceState(); to me it is actually an un-named phase where all the nodes are queried or informed to the platform; that seems fine to save the NULL on the mPcieFeatures[] table.

Thanks
Ashraf

> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Thursday, March 5, 2020 7:43 PM
> To: devel@edk2.groups.io; Ni, Ray <ray.ni@intel.com>; Javeed, Ashraf
> <ashraf.javeed@intel.com>
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> <hao.a.wu@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
> 
> Ashraf,
> I think it might be better to describe my review comments with code
> implementation.
> Can you please check this branch where I did some modification based on
> your code?
> https://github.com/niruiyu/edk2/tree/pci/pcie2
> 
> Let's firstly align on the feature initialization framework implementation.
> To be specific, this commit:
> MdeModulePkg/PciBus: Add the framework to init PCIE features
> https://github.com/niruiyu/edk2/commit/9fb9a3dcef06de98a76825e2fc0
> 7167446ee6fd9
> 
> Thanks,
> Ray
> 
> > -----Original Message-----
> > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Ni,
> Ray
> > Sent: Thursday, December 19, 2019 1:49 PM
> > To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > <hao.a.wu@intel.com>
> > Subject: Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > 05/12]
> > PciBusDxe: Setup sub-phases for PCI feature enumeration
> >
> > After I reviewed the patch of enabling MaxPayloadSize, MaxReadReqSize
> > and more PCIE features, I can now understand the phases more than
> > earlier.
> >
> > Your patch proposed five phases:
> >   //
> >   // 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
> >
> >
> > I have several comments to the five phases.
> > 1. Scan phase is not do the scanning but creates a list to hold all
> > root ports under the root bridge.
> > 2. Root ports collection is not required by all of the features, only
> > by MPS and MRRS.
> > But the collection always happens even when platform doesn't require
> > PciBus to initialize MPS or MRRS.
> > 3. GetDevicePolicy phase is not just call the GetDevicePolicy for each
> > device. It also reads the PCIE configuration space to get the device's
> > feature related capabilities, for some of the features.
> >
> > With that, I propose to define 4 phases:
> > 1. Initialize phase
> > This phase is similar to your Scan phase.
> > For some features, this phase does nothing.
> > For MPS and MRRS, this phase creates a list holding all root ports.
> >
> > 2. Scan phase
> > This phase is similar to your GetDevicePolicy phase.
> > For some features, this phase needs nothing do to.
> > For MPS and MRRS, this phase scan all devices and get the aligned
> > value of MPS or MRRS.
> >
> > 3. Program phase or Configuration phase This phase is similar to your
> > Configuration phase.
> > The Setup phase can be merged to this phase.
> >
> > 4. Finalize phase.
> > This phase is similar to your ConfigurationComplete phase.
> > This phase frees the resources occupied/allocated in Initialize phase.
> > For some of the features, this phase may do nothing.
> >
> > Each feature needs to provide function pointers for each phase and
> > NULL means the feature doesn't need to do anything in the specific
> > phase.
> > With that, we can define a structure:
> > Typedef struct {
> >   BOOLEAN                          Enable;
> >   PCIE_FEATURE_INITILAIZE Initialize;
> >   PCIE_FEATURE_SCAN  Scan;
> >   PCIE_FEATURE_PROGRAM Program;
> >   PCIE_FEATURE_FINALIZE Finalize;
> > } PCIE_FEATURE_ENTRY;
> >
> > With that, we can define a module level global variable:
> > PCIE_FEATURE_ENTRY mPcieFeatures[] = {
> >   { TRUE, MaxPayloadInitialize, MaxPayloadScan, MaxPayloadProgram,
> > MaxPayloadFinalize},
> >   { TRUE, MaxReadRequestInitialize, MaxReadRequestScan,
> > MaxReadRequestProgram, MaxReadRequestFinalize},
> >   { TRUE, NULL, NULL, RelaxOrderProgram, NULL},
> >   { TRUE, NULL, CompletionTimeoutScan, CompletionTimeoutProgram,
> NULL },
> >   ...
> > };
> >
> > PCIE_FEATURE_ENTRY.Enable can be set to FALSE according to the
> > platform policy.
> >
> > The enable of PCIE features can be written as a feature agnostic for-loop.
> > This can make the new feature enabling code easy to add and review.
> >
> >
> > > -----Original Message-----
> > > From: Javeed, Ashraf <ashraf.javeed@intel.com>
> > > Sent: Wednesday, December 18, 2019 3:14 PM
> > > To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > <hao.a.wu@intel.com>
> > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > > 05/12]
> > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > >
> > > Thanks for the review, Ray!
> > > My response in line
> > >
> > > > -----Original Message-----
> > > > From: Ni, Ray <ray.ni@intel.com>
> > > > Sent: Tuesday, December 17, 2019 5:26 PM
> > > > To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > <hao.a.wu@intel.com>
> > > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > > 05/12]
> > > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > >
> > > > Please check comments below.
> > > > I may have more comments regarding to the four phases after I
> > > > finish
> > > review of
> > > > further patches.
> > > >
> > > > Besides the comments below, I have a general comments to the debug
> > > > message: can you please review the existing debug message in the
> > > > PciBus
> > > driver
> > > > and make sure your newly added debug message aligns to existing
> style.
> > > And try
> > > > to use less lines of debug messages with still enough debug
> information.
> > > Ok, will look into that.
> > >
> > > >
> > > > > > +PRIMARY_ROOT_PORT_NODE
> *mPrimaryRootPortList;
> > > > > > +
> > > > > > +/**
> > > > > > +  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;
> > > >
> > > > 1. Please follow existing linked list usage style. The first node
> > > > in the list is an empty header node.
> > > >
> > > > LIST_ENTRY   mPrimaryRootPortList;
> > > > LIST_ENTRY   mPciFeaturesConfigurationCompletionList;
> > > >
> > > Ok, will make the change when I incorporate the ECR 0.75 or greater
> version.
> > >
> > > > > > +BOOLEAN
> > > > > > +CheckPciFeatureConfigurationRecordExist (
> > > > > > +  IN  PCI_IO_DEVICE                             *RootBridge,
> > > > > > +  OUT PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > > > +**PciFeatureConfigRecord
> > > > > > +  )
> > > >
> > > > 2. Is this function to check whether the PCIE features under a
> > > > root bridge is already initialized?
> > > > Can you use the existing variable gFullEnumeration?
> > > > The variable is set to TRUE when the enumeration is done to a host
> > > > bridge
> > > in the
> > > > first time.
> > > > By using gFullEnumeration, the entire function is not needed.
> > > >
> > > Ok, will look into this.
> > >
> > > > > > +EFI_STATUS AddRootBridgeInPciFeaturesConfigCompletionList (
> > > > > > +  IN PCI_IO_DEVICE          *RootBridge,
> > > > > > +  IN BOOLEAN                ReEnumerationRequired
> > > > > > +  )
> > > >
> > > > 3. Same question as #2. I think by using gFullEnumeration, this
> > > > function is
> > > not
> > > > needed.
> > > >
> > > OK
> > >
> > > >
> > > > > > +BOOLEAN
> > > > > > +IsPciRootPortEmpty (
> > > > > > +  IN  PCI_IO_DEVICE                           *PciDevice
> > > > > > +  )
> > > >
> > > > 4. Please use IsListEmpty() directly from callers and remove this
> function.
> > > >
> > > Will consider this.
> > >
> > > > > > +**/
> > > > > > +EFI_STATUS
> > > > > > +EnumerateOtherPciFeatures (
> > > >
> > > > 5. Can it be "EnumeratePcieFeatures"?
> > > >
> > > Yes, with the change to ECR 0.75, this routine name shall be changed.
> > >
> > > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > > > +  )
> > > > > > +{
> > > > > > +  EFI_STATUS            Status;
> > > > > > +  UINTN                 OtherPciFeatureConfigPhase;
> > > > > > +
> > > > > > +  //
> > > > > > +  // check on PCI features configuration is complete and
> > > > > > + re-enumeration is required  //  if
> > > > > > + (!CheckPciFeaturesConfigurationRequired
> > > > > > + (RootBridge)) {
> > > > > > +    return EFI_ALREADY_STARTED;  }
> > > > > > +
> > > >  > > +  CHAR16                *Str;
> > > > > > +  Str = ConvertDevicePathToText (
> > > > > > +          DevicePathFromHandle (RootBridge->Handle),
> > > > > > +          FALSE,
> > > > > > +          FALSE
> > > > > > +        );
> > > > > > +  DEBUG ((DEBUG_INFO, "Enumerating PCI features for Root
> > > > > > + Bridge %s\n", Str != NULL ? Str : L""));
> > > >
> > > > 6. Please use DEBUG_CODE macro to include
> > > > ConvertDevicePathToText()
> > > and
> > > > DEBUG().
> > > > Please remember to call FreePool().
> > > >
> > > Ok, will can under DEBUG_CODE, and free pool is called in the end
> > >
> > > > > > +
> > > > > > +  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);
> > > >
> > > > 7. How about "RecordPciRootPorts (RootBridge)"? The "Bridges"
> > > > suffix is a
> > > bit
> > > > confusing.
> > > >
> > > Fine, will change.
> > >
> > > > > > +      case  PciFeatureGetDevicePolicy:
> > > > > > +      case  PciFeatureSetupPhase:
> > > >
> > > > 8. In SetupPciFeatures(), why do you need to call DeviceExist()?
> > > > Did you see any case that a device is detected in the beginning of
> > > > PciBus
> > > scan
> > > > but is hidden when calling SetupPciFeatures()?
> > > >
> > > Yes, that is the case; device detected during the beginning of
> > > PciBus scan appears to be hidden by the platform drivers, since
> > > numerous legacy callbacks are initiated at different phase of PCI
> > > enumeration to the PCI Host Bridge, and PciPlatform drivers.
> > > This can be avoided if the PciBus driver is enhanced to check for
> > > PCI device existence before the publication of the PCI IO Protocol,
> > > and removal of the PCI_IO_DEVICE instance from the linked list.
> > >
> > > > 9. In GetPciFeaturesConfigurationTable() when checking whether a
> > > > PCI
> > > device
> > > > belongs to a root port, we can use below simpler logic:
> > > >   SizeOfPciDevicePath = GetDevicePathSize (PciDevicePath);
> > > >   SizeOfRootPortDevicePath = GetDevicePathSize (RootPortPath);
> > > >   if ((SizeOfRootPortDevicePath < SizeOfPciDevicePath) &&
> > > >       CompareMem (PciDevicePath, RootPortPath,
> > > SizeOfRootPortDevicePath -
> > > > END_DEVICE_PATH_LENGTH) == 0)) {
> > > >     // PCI device belongs to the root port.
> > > >   }
> > > >
> > > Ok.
> > >
> > > > > > +        Status = ProgramPciFeatures (RootBridge);
> > > > 10. ProgramPcieFeatures()?
> > > >
> > > OK
> > >
> > > > > > +
> > > > > > +  if (Str != NULL) {
> > > > > > +    FreePool (Str);
> > > > > > +  }
> > > >
> > > > 11. OK the Str is freed here because Str is needed for other debug
> > > messages
> > > > inside the function.
> > > >
> > > Yes
> > >
> > > > > > +  //
> > > > > > +  // mark this root bridge as PCI features configuration
> > > > > > +complete, and no new
> > > > > > +  // enumeration is required
> > > > > > +  //
> > > > > > +  AddRootBridgeInPciFeaturesConfigCompletionList (RootBridge,
> > > > > > +FALSE);
> > > >
> > > > 12. Not needed.
> > > >
> > > ok, after incorporating the logic of gFullEnumeration it won't be
> > > required
> > >
> > > > > > +_PRIMARY_ROOT_PORT_NODE {
> > > >
> > > > > > +  //
> > > > > > +  // Signature header
> > > > > > +  //
> > > > > > +  UINT32                                    Signature;
> > > > > > +  //
> > > > > > +  // linked list pointers to next node
> > > > > > +  //
> > > > > > +  LIST_ENTRY                                NeighborRootPort;
> > > > > > +  //
> > > > > > +  // pointer to PCI_IO_DEVICE of the primary PCI Controller
> > > > > > +device
> > > > > > +  //
> > > > > > +  EFI_DEVICE_PATH_PROTOCOL                  *RootPortDevicePath;
> > > > > > +  //
> > > > > > +  // pointer to the corresponding PCI feature configuration
> > > > > > +Table node
> > > > > > +  // all the child PCI devices of the controller are aligned
> > > > > > +based on this table
> > > > > > +  //
> > > > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > *OtherPciFeaturesConfigurationTable;
> > > > > > +};
> > > >
> > > > 13. Can you add the OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> field
> > > to
> > > > PCI_IO_DEVICE structure?
> > > > So this structure PRIMARY_ROOT_PORT_NODE is not needed.
> > > >
> > > I think it is better to maintain separately as this configuration
> > > table is confined to a group of PCI devices and for the RCiEP it is
> > > not applicable hence not required. Moreover, I am maintaining a
> > > variable for each PCIe feature in the PCI_IO_DEVICE; perhaps I can
> consider having just pointer of it....
> > >
> > > > > > +struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
> > > > 14. This structure is not needed if using gFullEnumeration.
> > > Yes.
> >
> > 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
  2020-03-16  9:33             ` Javeed, Ashraf
@ 2020-03-16 14:00               ` Ni, Ray
  2020-03-17  7:20                 ` Javeed, Ashraf
  0 siblings, 1 reply; 51+ messages in thread
From: Ni, Ray @ 2020-03-16 14:00 UTC (permalink / raw)
  To: Javeed, Ashraf, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

Ashraf,
Thanks for taking time to review my code! Comments embedded in below.

> -----Original Message-----
> From: Javeed, Ashraf <ashraf.javeed@intel.com>
> Sent: Monday, March 16, 2020 5:34 PM
> To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature
> enumeration
> 
> Ray,
> First of all, thank you for taking time to review and on optimizing the PCIe feature support in the PciBusDxe.
> 
> I shall not discuss everything in detail here, just want to bring two major points:-
> 
> (1)  commit:- MdePkg: New PCI Express Platform/Override Protocols
> https://github.com/niruiyu/edk2/commit/52524e9654704a7f6a30ca446f215b81fe8f0984
> PCI Express Protocol not as per the ECR draft revision 0.8, the changes made has to be reviewed with updated ECR
> version...

With the code first process, we could firstly finalize the protocol interfaces in code then update the ECR.
Code first doesn't mean implementation detail has high priority than protocol interfaces. Good quality of protocol interfaces is still desired. The quality of the protocol header file is always in high priority.

> the global auto option introduces EFI_PCI_EXPRESS_DEVICE_POLICY_AUTO; is used for MPS, MRRS, RO, NS, AtomicOp, LTR,
> results in no EFI encodings required for these
> features, as it can be used with actual values from the PciXX.h definitions. This do result in lot of code savings.

I take it as an agree of using the global AUTO. Thanks for that.

> 
> (2) commit:- MdeModulePkg/PciBus: Add the framework to init PCIE features
> https://github.com/niruiyu/edk2/commit/9fb9a3dcef06de98a76825e2fc07167446ee6fd9
> The context handling of the PCIe feature MPS has fundamental issue as it is set to be common for all the nodes of the
> parent  Root Bridge instance. The context has to be separate to each first level nodes of a root bridge instance. For
> example, a root bridge has 1 RCiEP and two Root ports, than there has to be 3 separate context for each. Since Root port
> can have its Endpoint device, or it can have a PCIe switch with 1 upstream and 2 or more downstream ports and to each
> downstream port an Endpoint device can be connected; the context created for Root Port of an bridge is used for all its
> child hierarchy nodes; thus PCIe feature like Max_Payload_Size value can be specific to each RCiEP, and each Root ports of
> the Root Bridge handle. How do you propose to maintain separate context for just first level nodes of the Root Bridge
> handle?

Supposing a root bridge contains 1 RCiEP and two root ports, the implementation ensures there will be 3 separate contexts for each. As you can see, every time the code starts enumeration from a RCiEP or a root port, a new Context[] is setup. Context[i] is associated with the feature _i_.


> 
> The EnumeratePcieDevices() is recursively calls itself for every PCI node with a level advanced by 1. Thus, the usage of level
> N and N+1 as parent and its child is wrong to me, when you have a PCIe switch below the Root Port, and N & N+1 will not
> be direct relation between the upstream port and its second downstream port...any reason why you have not used the
> PCI_IO_DEVICE.Parent pointer to form relation between the parent and the child?

The level N and N+1 is needed for AtomicOp or Ltr feature (which I need to go back to check the code).
I want to avoid the individual feature scan/program routine checks device's parent/children.
I understand that in PCIE spec, a switch consists of an upstream port and several downstream ports.
It means a switch populates a bridge which connects to the upstream and several bridges under the upstream bridge which connect to the downstream.
But from software perspective, I don't think we should care about that.
Maybe I am wrong. Can you please give a real example that treating in my way would cause some issues?

> 
> I liked the Pre & Post order flag that is used to processing parent-to-child vs. child-to-parent nodes. 

Actually I didn't have this flag in the first version of my code change. But later I found it's needed for some features like LTR which needs to be programmed from rootbridge to endpoint according to spec.


> You are calling the first
> and last features as fakes, when you actually parse all the nodes for the GetDevicePolicy() and NotifyDeviceState(); to me it
> is actually an un-named phase where all the nodes are queried or informed to the platform; that seems fine to save the
> NULL on the mPcieFeatures[] table.

Yes I put GetDevicePolicy() and NotifyDeviceState() in the feature array in my first version of code. And later I called the two separately for better code readability. But it was my fault that I didn't update the commit message. It caused confusion to you.

> 
> Thanks
> Ashraf
> 
> > -----Original Message-----
> > From: Ni, Ray <ray.ni@intel.com>
> > Sent: Thursday, March 5, 2020 7:43 PM
> > To: devel@edk2.groups.io; Ni, Ray <ray.ni@intel.com>; Javeed, Ashraf
> > <ashraf.javeed@intel.com>
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > <hao.a.wu@intel.com>
> > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
> >
> > Ashraf,
> > I think it might be better to describe my review comments with code
> > implementation.
> > Can you please check this branch where I did some modification based on
> > your code?
> > https://github.com/niruiyu/edk2/tree/pci/pcie2
> >
> > Let's firstly align on the feature initialization framework implementation.
> > To be specific, this commit:
> > MdeModulePkg/PciBus: Add the framework to init PCIE features
> > https://github.com/niruiyu/edk2/commit/9fb9a3dcef06de98a76825e2fc0
> > 7167446ee6fd9
> >
> > Thanks,
> > Ray
> >
> > > -----Original Message-----
> > > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Ni,
> > Ray
> > > Sent: Thursday, December 19, 2019 1:49 PM
> > > To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > <hao.a.wu@intel.com>
> > > Subject: Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > > 05/12]
> > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > >
> > > After I reviewed the patch of enabling MaxPayloadSize, MaxReadReqSize
> > > and more PCIE features, I can now understand the phases more than
> > > earlier.
> > >
> > > Your patch proposed five phases:
> > >   //
> > >   // 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
> > >
> > >
> > > I have several comments to the five phases.
> > > 1. Scan phase is not do the scanning but creates a list to hold all
> > > root ports under the root bridge.
> > > 2. Root ports collection is not required by all of the features, only
> > > by MPS and MRRS.
> > > But the collection always happens even when platform doesn't require
> > > PciBus to initialize MPS or MRRS.
> > > 3. GetDevicePolicy phase is not just call the GetDevicePolicy for each
> > > device. It also reads the PCIE configuration space to get the device's
> > > feature related capabilities, for some of the features.
> > >
> > > With that, I propose to define 4 phases:
> > > 1. Initialize phase
> > > This phase is similar to your Scan phase.
> > > For some features, this phase does nothing.
> > > For MPS and MRRS, this phase creates a list holding all root ports.
> > >
> > > 2. Scan phase
> > > This phase is similar to your GetDevicePolicy phase.
> > > For some features, this phase needs nothing do to.
> > > For MPS and MRRS, this phase scan all devices and get the aligned
> > > value of MPS or MRRS.
> > >
> > > 3. Program phase or Configuration phase This phase is similar to your
> > > Configuration phase.
> > > The Setup phase can be merged to this phase.
> > >
> > > 4. Finalize phase.
> > > This phase is similar to your ConfigurationComplete phase.
> > > This phase frees the resources occupied/allocated in Initialize phase.
> > > For some of the features, this phase may do nothing.
> > >
> > > Each feature needs to provide function pointers for each phase and
> > > NULL means the feature doesn't need to do anything in the specific
> > > phase.
> > > With that, we can define a structure:
> > > Typedef struct {
> > >   BOOLEAN                          Enable;
> > >   PCIE_FEATURE_INITILAIZE Initialize;
> > >   PCIE_FEATURE_SCAN  Scan;
> > >   PCIE_FEATURE_PROGRAM Program;
> > >   PCIE_FEATURE_FINALIZE Finalize;
> > > } PCIE_FEATURE_ENTRY;
> > >
> > > With that, we can define a module level global variable:
> > > PCIE_FEATURE_ENTRY mPcieFeatures[] = {
> > >   { TRUE, MaxPayloadInitialize, MaxPayloadScan, MaxPayloadProgram,
> > > MaxPayloadFinalize},
> > >   { TRUE, MaxReadRequestInitialize, MaxReadRequestScan,
> > > MaxReadRequestProgram, MaxReadRequestFinalize},
> > >   { TRUE, NULL, NULL, RelaxOrderProgram, NULL},
> > >   { TRUE, NULL, CompletionTimeoutScan, CompletionTimeoutProgram,
> > NULL },
> > >   ...
> > > };
> > >
> > > PCIE_FEATURE_ENTRY.Enable can be set to FALSE according to the
> > > platform policy.
> > >
> > > The enable of PCIE features can be written as a feature agnostic for-loop.
> > > This can make the new feature enabling code easy to add and review.
> > >
> > >
> > > > -----Original Message-----
> > > > From: Javeed, Ashraf <ashraf.javeed@intel.com>
> > > > Sent: Wednesday, December 18, 2019 3:14 PM
> > > > To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > <hao.a.wu@intel.com>
> > > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > > > 05/12]
> > > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > >
> > > > Thanks for the review, Ray!
> > > > My response in line
> > > >
> > > > > -----Original Message-----
> > > > > From: Ni, Ray <ray.ni@intel.com>
> > > > > Sent: Tuesday, December 17, 2019 5:26 PM
> > > > > To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > <hao.a.wu@intel.com>
> > > > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > > > 05/12]
> > > > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > > >
> > > > > Please check comments below.
> > > > > I may have more comments regarding to the four phases after I
> > > > > finish
> > > > review of
> > > > > further patches.
> > > > >
> > > > > Besides the comments below, I have a general comments to the debug
> > > > > message: can you please review the existing debug message in the
> > > > > PciBus
> > > > driver
> > > > > and make sure your newly added debug message aligns to existing
> > style.
> > > > And try
> > > > > to use less lines of debug messages with still enough debug
> > information.
> > > > Ok, will look into that.
> > > >
> > > > >
> > > > > > > +PRIMARY_ROOT_PORT_NODE
> > *mPrimaryRootPortList;
> > > > > > > +
> > > > > > > +/**
> > > > > > > +  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;
> > > > >
> > > > > 1. Please follow existing linked list usage style. The first node
> > > > > in the list is an empty header node.
> > > > >
> > > > > LIST_ENTRY   mPrimaryRootPortList;
> > > > > LIST_ENTRY   mPciFeaturesConfigurationCompletionList;
> > > > >
> > > > Ok, will make the change when I incorporate the ECR 0.75 or greater
> > version.
> > > >
> > > > > > > +BOOLEAN
> > > > > > > +CheckPciFeatureConfigurationRecordExist (
> > > > > > > +  IN  PCI_IO_DEVICE                             *RootBridge,
> > > > > > > +  OUT PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > > > > +**PciFeatureConfigRecord
> > > > > > > +  )
> > > > >
> > > > > 2. Is this function to check whether the PCIE features under a
> > > > > root bridge is already initialized?
> > > > > Can you use the existing variable gFullEnumeration?
> > > > > The variable is set to TRUE when the enumeration is done to a host
> > > > > bridge
> > > > in the
> > > > > first time.
> > > > > By using gFullEnumeration, the entire function is not needed.
> > > > >
> > > > Ok, will look into this.
> > > >
> > > > > > > +EFI_STATUS AddRootBridgeInPciFeaturesConfigCompletionList (
> > > > > > > +  IN PCI_IO_DEVICE          *RootBridge,
> > > > > > > +  IN BOOLEAN                ReEnumerationRequired
> > > > > > > +  )
> > > > >
> > > > > 3. Same question as #2. I think by using gFullEnumeration, this
> > > > > function is
> > > > not
> > > > > needed.
> > > > >
> > > > OK
> > > >
> > > > >
> > > > > > > +BOOLEAN
> > > > > > > +IsPciRootPortEmpty (
> > > > > > > +  IN  PCI_IO_DEVICE                           *PciDevice
> > > > > > > +  )
> > > > >
> > > > > 4. Please use IsListEmpty() directly from callers and remove this
> > function.
> > > > >
> > > > Will consider this.
> > > >
> > > > > > > +**/
> > > > > > > +EFI_STATUS
> > > > > > > +EnumerateOtherPciFeatures (
> > > > >
> > > > > 5. Can it be "EnumeratePcieFeatures"?
> > > > >
> > > > Yes, with the change to ECR 0.75, this routine name shall be changed.
> > > >
> > > > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > > > > +  )
> > > > > > > +{
> > > > > > > +  EFI_STATUS            Status;
> > > > > > > +  UINTN                 OtherPciFeatureConfigPhase;
> > > > > > > +
> > > > > > > +  //
> > > > > > > +  // check on PCI features configuration is complete and
> > > > > > > + re-enumeration is required  //  if
> > > > > > > + (!CheckPciFeaturesConfigurationRequired
> > > > > > > + (RootBridge)) {
> > > > > > > +    return EFI_ALREADY_STARTED;  }
> > > > > > > +
> > > > >  > > +  CHAR16                *Str;
> > > > > > > +  Str = ConvertDevicePathToText (
> > > > > > > +          DevicePathFromHandle (RootBridge->Handle),
> > > > > > > +          FALSE,
> > > > > > > +          FALSE
> > > > > > > +        );
> > > > > > > +  DEBUG ((DEBUG_INFO, "Enumerating PCI features for Root
> > > > > > > + Bridge %s\n", Str != NULL ? Str : L""));
> > > > >
> > > > > 6. Please use DEBUG_CODE macro to include
> > > > > ConvertDevicePathToText()
> > > > and
> > > > > DEBUG().
> > > > > Please remember to call FreePool().
> > > > >
> > > > Ok, will can under DEBUG_CODE, and free pool is called in the end
> > > >
> > > > > > > +
> > > > > > > +  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);
> > > > >
> > > > > 7. How about "RecordPciRootPorts (RootBridge)"? The "Bridges"
> > > > > suffix is a
> > > > bit
> > > > > confusing.
> > > > >
> > > > Fine, will change.
> > > >
> > > > > > > +      case  PciFeatureGetDevicePolicy:
> > > > > > > +      case  PciFeatureSetupPhase:
> > > > >
> > > > > 8. In SetupPciFeatures(), why do you need to call DeviceExist()?
> > > > > Did you see any case that a device is detected in the beginning of
> > > > > PciBus
> > > > scan
> > > > > but is hidden when calling SetupPciFeatures()?
> > > > >
> > > > Yes, that is the case; device detected during the beginning of
> > > > PciBus scan appears to be hidden by the platform drivers, since
> > > > numerous legacy callbacks are initiated at different phase of PCI
> > > > enumeration to the PCI Host Bridge, and PciPlatform drivers.
> > > > This can be avoided if the PciBus driver is enhanced to check for
> > > > PCI device existence before the publication of the PCI IO Protocol,
> > > > and removal of the PCI_IO_DEVICE instance from the linked list.
> > > >
> > > > > 9. In GetPciFeaturesConfigurationTable() when checking whether a
> > > > > PCI
> > > > device
> > > > > belongs to a root port, we can use below simpler logic:
> > > > >   SizeOfPciDevicePath = GetDevicePathSize (PciDevicePath);
> > > > >   SizeOfRootPortDevicePath = GetDevicePathSize (RootPortPath);
> > > > >   if ((SizeOfRootPortDevicePath < SizeOfPciDevicePath) &&
> > > > >       CompareMem (PciDevicePath, RootPortPath,
> > > > SizeOfRootPortDevicePath -
> > > > > END_DEVICE_PATH_LENGTH) == 0)) {
> > > > >     // PCI device belongs to the root port.
> > > > >   }
> > > > >
> > > > Ok.
> > > >
> > > > > > > +        Status = ProgramPciFeatures (RootBridge);
> > > > > 10. ProgramPcieFeatures()?
> > > > >
> > > > OK
> > > >
> > > > > > > +
> > > > > > > +  if (Str != NULL) {
> > > > > > > +    FreePool (Str);
> > > > > > > +  }
> > > > >
> > > > > 11. OK the Str is freed here because Str is needed for other debug
> > > > messages
> > > > > inside the function.
> > > > >
> > > > Yes
> > > >
> > > > > > > +  //
> > > > > > > +  // mark this root bridge as PCI features configuration
> > > > > > > +complete, and no new
> > > > > > > +  // enumeration is required
> > > > > > > +  //
> > > > > > > +  AddRootBridgeInPciFeaturesConfigCompletionList (RootBridge,
> > > > > > > +FALSE);
> > > > >
> > > > > 12. Not needed.
> > > > >
> > > > ok, after incorporating the logic of gFullEnumeration it won't be
> > > > required
> > > >
> > > > > > > +_PRIMARY_ROOT_PORT_NODE {
> > > > >
> > > > > > > +  //
> > > > > > > +  // Signature header
> > > > > > > +  //
> > > > > > > +  UINT32                                    Signature;
> > > > > > > +  //
> > > > > > > +  // linked list pointers to next node
> > > > > > > +  //
> > > > > > > +  LIST_ENTRY                                NeighborRootPort;
> > > > > > > +  //
> > > > > > > +  // pointer to PCI_IO_DEVICE of the primary PCI Controller
> > > > > > > +device
> > > > > > > +  //
> > > > > > > +  EFI_DEVICE_PATH_PROTOCOL                  *RootPortDevicePath;
> > > > > > > +  //
> > > > > > > +  // pointer to the corresponding PCI feature configuration
> > > > > > > +Table node
> > > > > > > +  // all the child PCI devices of the controller are aligned
> > > > > > > +based on this table
> > > > > > > +  //
> > > > > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > > *OtherPciFeaturesConfigurationTable;
> > > > > > > +};
> > > > >
> > > > > 13. Can you add the OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > field
> > > > to
> > > > > PCI_IO_DEVICE structure?
> > > > > So this structure PRIMARY_ROOT_PORT_NODE is not needed.
> > > > >
> > > > I think it is better to maintain separately as this configuration
> > > > table is confined to a group of PCI devices and for the RCiEP it is
> > > > not applicable hence not required. Moreover, I am maintaining a
> > > > variable for each PCIe feature in the PCI_IO_DEVICE; perhaps I can
> > consider having just pointer of it....
> > > >
> > > > > > > +struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
> > > > > 14. This structure is not needed if using gFullEnumeration.
> > > > Yes.
> > >
> > > 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
  2020-03-16 14:00               ` Ni, Ray
@ 2020-03-17  7:20                 ` Javeed, Ashraf
  2020-03-17 15:36                   ` Ni, Ray
  0 siblings, 1 reply; 51+ messages in thread
From: Javeed, Ashraf @ 2020-03-17  7:20 UTC (permalink / raw)
  To: Ni, Ray, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

My response below.
Thanks
Ashraf

> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Monday, March 16, 2020 7:30 PM
> To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> <hao.a.wu@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
> 
> Ashraf,
> Thanks for taking time to review my code! Comments embedded in below.
> 
> > -----Original Message-----
> > From: Javeed, Ashraf <ashraf.javeed@intel.com>
> > Sent: Monday, March 16, 2020 5:34 PM
> > To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > <hao.a.wu@intel.com>
> > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
> >
> > Ray,
> > First of all, thank you for taking time to review and on optimizing the PCIe
> feature support in the PciBusDxe.
> >
> > I shall not discuss everything in detail here, just want to bring two
> > major points:-
> >
> > (1)  commit:- MdePkg: New PCI Express Platform/Override Protocols
> >
> https://github.com/niruiyu/edk2/commit/52524e9654704a7f6a30ca446f2
> 15b8
> > 1fe8f0984 PCI Express Protocol not as per the ECR draft revision 0.8,
> > the changes made has to be reviewed with updated ECR version...
> 
> With the code first process, we could firstly finalize the protocol interfaces
> in code then update the ECR.
> Code first doesn't mean implementation detail has high priority than
> protocol interfaces. Good quality of protocol interfaces is still desired. The
> quality of the protocol header file is always in high priority.
> 
> > the global auto option introduces
> EFI_PCI_EXPRESS_DEVICE_POLICY_AUTO;
> > is used for MPS, MRRS, RO, NS, AtomicOp, LTR, results in no EFI
> > encodings required for these features, as it can be used with actual values
> from the PciXX.h definitions. This do result in lot of code savings.
> 
> I take it as an agree of using the global AUTO. Thanks for that.
Please note that there is another request of "Do not touch", and I am still contemplating whether both AUTO and DO_NOT_TOUCH options could be applicable to all the PCIe features or not. It could be possible to take AUTO for some of them and DO_NOT_TOUCH for others. Need to consider each PCIe feature separately for both these options.
 
> 
> >
> > (2) commit:- MdeModulePkg/PciBus: Add the framework to init PCIE
> > features
> >
> https://github.com/niruiyu/edk2/commit/9fb9a3dcef06de98a76825e2fc0
> 7167
> > 446ee6fd9 The context handling of the PCIe feature MPS has fundamental
> > issue as it is set to be common for all the nodes of the parent  Root
> > Bridge instance. The context has to be separate to each first level
> > nodes of a root bridge instance. For example, a root bridge has 1
> > RCiEP and two Root ports, than there has to be 3 separate context for
> > each. Since Root port can have its Endpoint device, or it can have a
> > PCIe switch with 1 upstream and 2 or more downstream ports and to
> each
> > downstream port an Endpoint device can be connected; the context
> > created for Root Port of an bridge is used for all its child hierarchy nodes;
> thus PCIe feature like Max_Payload_Size value can be specific to each RCiEP,
> and each Root ports of the Root Bridge handle. How do you propose to
> maintain separate context for just first level nodes of the Root Bridge
> handle?
> 
> Supposing a root bridge contains 1 RCiEP and two root ports, the
> implementation ensures there will be 3 separate contexts for each. As you
> can see, every time the code starts enumeration from a RCiEP or a root
> port, a new Context[] is setup. Context[i] is associated with the feature _i_.
> 
I realize now, that there are 3 nested for-loops in the EnumerateRootBridgePcieFeatures(), the first one enables the processing of first level nodes of the Root Bridge instance, and in this way the context[i] used for each node will be valid as it covers each node's hierarchy.

> 
> >
> > The EnumeratePcieDevices() is recursively calls itself for every PCI
> > node with a level advanced by 1. Thus, the usage of level N and N+1 as
> > parent and its child is wrong to me, when you have a PCIe switch below
> > the Root Port, and N & N+1 will not be direct relation between the
> upstream port and its second downstream port...any reason why you have
> not used the PCI_IO_DEVICE.Parent pointer to form relation between the
> parent and the child?
> 
> The level N and N+1 is needed for AtomicOp or Ltr feature (which I need to
> go back to check the code).
> I want to avoid the individual feature scan/program routine checks device's
> parent/children.
> I understand that in PCIE spec, a switch consists of an upstream port and
> several downstream ports.
> It means a switch populates a bridge which connects to the upstream and
> several bridges under the upstream bridge which connect to the
> downstream.
> But from software perspective, I don't think we should care about that.
> Maybe I am wrong. Can you please give a real example that treating in my
> way would cause some issues?
> 
Let just say we have PCIe switch connected to Root Port on a host, and it has 2 downstream ports, each connected to one Endpoint device each. Platform has selected to enable LTR for second downstream port's endpoint device, not both. As per your code logic of LTR, where you use the N and N+1 to compare between the parent and child, will not be applicable if you use the same condition to check downstream port (N+1), and its parent upstream port, because N would be the Endpoint device of first downstream port of the PCIe switch and not its upstream port.
Root Port ->					1|0|0
Switch upstream port ->				2|0|0 (M-1)
Switch downstream ports ->	3|0|0,(M)		5|0|0 (N (=M+2))
Endpoint devices ->		4|0|0 (M+1)		6|0|0 (N+1 (=M+3))
The level+1 logic when the EnumeratePcieDevices() is called recursively, will result in one value greater than the Endpoint device for the second downstream port. 

> >
> > I liked the Pre & Post order flag that is used to processing parent-to-child
> vs. child-to-parent nodes.
> 
> Actually I didn't have this flag in the first version of my code change. But
> later I found it's needed for some features like LTR which needs to be
> programmed from rootbridge to endpoint according to spec.
> 
> 
> > You are calling the first
> > and last features as fakes, when you actually parse all the nodes for
> > the GetDevicePolicy() and NotifyDeviceState(); to me it is actually an
> > un-named phase where all the nodes are queried or informed to the
> platform; that seems fine to save the NULL on the mPcieFeatures[] table.
> 
> Yes I put GetDevicePolicy() and NotifyDeviceState() in the feature array in
> my first version of code. And later I called the two separately for better
> code readability. But it was my fault that I didn't update the commit
> message. It caused confusion to you.
> 
> >
> > Thanks
> > Ashraf
> >
> > > -----Original Message-----
> > > From: Ni, Ray <ray.ni@intel.com>
> > > Sent: Thursday, March 5, 2020 7:43 PM
> > > To: devel@edk2.groups.io; Ni, Ray <ray.ni@intel.com>; Javeed, Ashraf
> > > <ashraf.javeed@intel.com>
> > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > <hao.a.wu@intel.com>
> > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > > 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
> > >
> > > Ashraf,
> > > I think it might be better to describe my review comments with code
> > > implementation.
> > > Can you please check this branch where I did some modification based
> > > on your code?
> > > https://github.com/niruiyu/edk2/tree/pci/pcie2
> > >
> > > Let's firstly align on the feature initialization framework
> implementation.
> > > To be specific, this commit:
> > > MdeModulePkg/PciBus: Add the framework to init PCIE features
> > >
> https://github.com/niruiyu/edk2/commit/9fb9a3dcef06de98a76825e2fc0
> > > 7167446ee6fd9
> > >
> > > Thanks,
> > > Ray
> > >
> > > > -----Original Message-----
> > > > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of
> Ni,
> > > Ray
> > > > Sent: Thursday, December 19, 2019 1:49 PM
> > > > To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > <hao.a.wu@intel.com>
> > > > Subject: Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > > > 05/12]
> > > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > >
> > > > After I reviewed the patch of enabling MaxPayloadSize,
> > > > MaxReadReqSize and more PCIE features, I can now understand the
> > > > phases more than earlier.
> > > >
> > > > Your patch proposed five phases:
> > > >   //
> > > >   // 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
> > > >
> > > >
> > > > I have several comments to the five phases.
> > > > 1. Scan phase is not do the scanning but creates a list to hold
> > > > all root ports under the root bridge.
> > > > 2. Root ports collection is not required by all of the features,
> > > > only by MPS and MRRS.
> > > > But the collection always happens even when platform doesn't
> > > > require PciBus to initialize MPS or MRRS.
> > > > 3. GetDevicePolicy phase is not just call the GetDevicePolicy for
> > > > each device. It also reads the PCIE configuration space to get the
> > > > device's feature related capabilities, for some of the features.
> > > >
> > > > With that, I propose to define 4 phases:
> > > > 1. Initialize phase
> > > > This phase is similar to your Scan phase.
> > > > For some features, this phase does nothing.
> > > > For MPS and MRRS, this phase creates a list holding all root ports.
> > > >
> > > > 2. Scan phase
> > > > This phase is similar to your GetDevicePolicy phase.
> > > > For some features, this phase needs nothing do to.
> > > > For MPS and MRRS, this phase scan all devices and get the aligned
> > > > value of MPS or MRRS.
> > > >
> > > > 3. Program phase or Configuration phase This phase is similar to
> > > > your Configuration phase.
> > > > The Setup phase can be merged to this phase.
> > > >
> > > > 4. Finalize phase.
> > > > This phase is similar to your ConfigurationComplete phase.
> > > > This phase frees the resources occupied/allocated in Initialize phase.
> > > > For some of the features, this phase may do nothing.
> > > >
> > > > Each feature needs to provide function pointers for each phase and
> > > > NULL means the feature doesn't need to do anything in the specific
> > > > phase.
> > > > With that, we can define a structure:
> > > > Typedef struct {
> > > >   BOOLEAN                          Enable;
> > > >   PCIE_FEATURE_INITILAIZE Initialize;
> > > >   PCIE_FEATURE_SCAN  Scan;
> > > >   PCIE_FEATURE_PROGRAM Program;
> > > >   PCIE_FEATURE_FINALIZE Finalize;
> > > > } PCIE_FEATURE_ENTRY;
> > > >
> > > > With that, we can define a module level global variable:
> > > > PCIE_FEATURE_ENTRY mPcieFeatures[] = {
> > > >   { TRUE, MaxPayloadInitialize, MaxPayloadScan, MaxPayloadProgram,
> > > > MaxPayloadFinalize},
> > > >   { TRUE, MaxReadRequestInitialize, MaxReadRequestScan,
> > > > MaxReadRequestProgram, MaxReadRequestFinalize},
> > > >   { TRUE, NULL, NULL, RelaxOrderProgram, NULL},
> > > >   { TRUE, NULL, CompletionTimeoutScan, CompletionTimeoutProgram,
> > > NULL },
> > > >   ...
> > > > };
> > > >
> > > > PCIE_FEATURE_ENTRY.Enable can be set to FALSE according to the
> > > > platform policy.
> > > >
> > > > The enable of PCIE features can be written as a feature agnostic for-
> loop.
> > > > This can make the new feature enabling code easy to add and review.
> > > >
> > > >
> > > > > -----Original Message-----
> > > > > From: Javeed, Ashraf <ashraf.javeed@intel.com>
> > > > > Sent: Wednesday, December 18, 2019 3:14 PM
> > > > > To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > <hao.a.wu@intel.com>
> > > > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2
> PATCH
> > > > > 05/12]
> > > > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > > >
> > > > > Thanks for the review, Ray!
> > > > > My response in line
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Ni, Ray <ray.ni@intel.com>
> > > > > > Sent: Tuesday, December 17, 2019 5:26 PM
> > > > > > To: Javeed, Ashraf <ashraf.javeed@intel.com>;
> > > > > > devel@edk2.groups.io
> > > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > > <hao.a.wu@intel.com>
> > > > > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2
> > > > > > PATCH
> > > > > 05/12]
> > > > > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > > > >
> > > > > > Please check comments below.
> > > > > > I may have more comments regarding to the four phases after I
> > > > > > finish
> > > > > review of
> > > > > > further patches.
> > > > > >
> > > > > > Besides the comments below, I have a general comments to the
> > > > > > debug
> > > > > > message: can you please review the existing debug message in
> > > > > > the PciBus
> > > > > driver
> > > > > > and make sure your newly added debug message aligns to
> > > > > > existing
> > > style.
> > > > > And try
> > > > > > to use less lines of debug messages with still enough debug
> > > information.
> > > > > Ok, will look into that.
> > > > >
> > > > > >
> > > > > > > > +PRIMARY_ROOT_PORT_NODE
> > > *mPrimaryRootPortList;
> > > > > > > > +
> > > > > > > > +/**
> > > > > > > > +  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;
> > > > > >
> > > > > > 1. Please follow existing linked list usage style. The first
> > > > > > node in the list is an empty header node.
> > > > > >
> > > > > > LIST_ENTRY   mPrimaryRootPortList;
> > > > > > LIST_ENTRY   mPciFeaturesConfigurationCompletionList;
> > > > > >
> > > > > Ok, will make the change when I incorporate the ECR 0.75 or
> > > > > greater
> > > version.
> > > > >
> > > > > > > > +BOOLEAN
> > > > > > > > +CheckPciFeatureConfigurationRecordExist (
> > > > > > > > +  IN  PCI_IO_DEVICE                             *RootBridge,
> > > > > > > > +  OUT PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > > > > > +**PciFeatureConfigRecord
> > > > > > > > +  )
> > > > > >
> > > > > > 2. Is this function to check whether the PCIE features under a
> > > > > > root bridge is already initialized?
> > > > > > Can you use the existing variable gFullEnumeration?
> > > > > > The variable is set to TRUE when the enumeration is done to a
> > > > > > host bridge
> > > > > in the
> > > > > > first time.
> > > > > > By using gFullEnumeration, the entire function is not needed.
> > > > > >
> > > > > Ok, will look into this.
> > > > >
> > > > > > > > +EFI_STATUS
> AddRootBridgeInPciFeaturesConfigCompletionList (
> > > > > > > > +  IN PCI_IO_DEVICE          *RootBridge,
> > > > > > > > +  IN BOOLEAN                ReEnumerationRequired
> > > > > > > > +  )
> > > > > >
> > > > > > 3. Same question as #2. I think by using gFullEnumeration,
> > > > > > this function is
> > > > > not
> > > > > > needed.
> > > > > >
> > > > > OK
> > > > >
> > > > > >
> > > > > > > > +BOOLEAN
> > > > > > > > +IsPciRootPortEmpty (
> > > > > > > > +  IN  PCI_IO_DEVICE                           *PciDevice
> > > > > > > > +  )
> > > > > >
> > > > > > 4. Please use IsListEmpty() directly from callers and remove
> > > > > > this
> > > function.
> > > > > >
> > > > > Will consider this.
> > > > >
> > > > > > > > +**/
> > > > > > > > +EFI_STATUS
> > > > > > > > +EnumerateOtherPciFeatures (
> > > > > >
> > > > > > 5. Can it be "EnumeratePcieFeatures"?
> > > > > >
> > > > > Yes, with the change to ECR 0.75, this routine name shall be
> changed.
> > > > >
> > > > > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > > > > > +  )
> > > > > > > > +{
> > > > > > > > +  EFI_STATUS            Status;
> > > > > > > > +  UINTN                 OtherPciFeatureConfigPhase;
> > > > > > > > +
> > > > > > > > +  //
> > > > > > > > +  // check on PCI features configuration is complete and
> > > > > > > > + re-enumeration is required  //  if
> > > > > > > > + (!CheckPciFeaturesConfigurationRequired
> > > > > > > > + (RootBridge)) {
> > > > > > > > +    return EFI_ALREADY_STARTED;  }
> > > > > > > > +
> > > > > >  > > +  CHAR16                *Str;
> > > > > > > > +  Str = ConvertDevicePathToText (
> > > > > > > > +          DevicePathFromHandle (RootBridge->Handle),
> > > > > > > > +          FALSE,
> > > > > > > > +          FALSE
> > > > > > > > +        );
> > > > > > > > +  DEBUG ((DEBUG_INFO, "Enumerating PCI features for Root
> > > > > > > > + Bridge %s\n", Str != NULL ? Str : L""));
> > > > > >
> > > > > > 6. Please use DEBUG_CODE macro to include
> > > > > > ConvertDevicePathToText()
> > > > > and
> > > > > > DEBUG().
> > > > > > Please remember to call FreePool().
> > > > > >
> > > > > Ok, will can under DEBUG_CODE, and free pool is called in the
> > > > > end
> > > > >
> > > > > > > > +
> > > > > > > > +  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);
> > > > > >
> > > > > > 7. How about "RecordPciRootPorts (RootBridge)"? The "Bridges"
> > > > > > suffix is a
> > > > > bit
> > > > > > confusing.
> > > > > >
> > > > > Fine, will change.
> > > > >
> > > > > > > > +      case  PciFeatureGetDevicePolicy:
> > > > > > > > +      case  PciFeatureSetupPhase:
> > > > > >
> > > > > > 8. In SetupPciFeatures(), why do you need to call DeviceExist()?
> > > > > > Did you see any case that a device is detected in the
> > > > > > beginning of PciBus
> > > > > scan
> > > > > > but is hidden when calling SetupPciFeatures()?
> > > > > >
> > > > > Yes, that is the case; device detected during the beginning of
> > > > > PciBus scan appears to be hidden by the platform drivers, since
> > > > > numerous legacy callbacks are initiated at different phase of
> > > > > PCI enumeration to the PCI Host Bridge, and PciPlatform drivers.
> > > > > This can be avoided if the PciBus driver is enhanced to check
> > > > > for PCI device existence before the publication of the PCI IO
> > > > > Protocol, and removal of the PCI_IO_DEVICE instance from the
> linked list.
> > > > >
> > > > > > 9. In GetPciFeaturesConfigurationTable() when checking whether
> > > > > > a PCI
> > > > > device
> > > > > > belongs to a root port, we can use below simpler logic:
> > > > > >   SizeOfPciDevicePath = GetDevicePathSize (PciDevicePath);
> > > > > >   SizeOfRootPortDevicePath = GetDevicePathSize (RootPortPath);
> > > > > >   if ((SizeOfRootPortDevicePath < SizeOfPciDevicePath) &&
> > > > > >       CompareMem (PciDevicePath, RootPortPath,
> > > > > SizeOfRootPortDevicePath -
> > > > > > END_DEVICE_PATH_LENGTH) == 0)) {
> > > > > >     // PCI device belongs to the root port.
> > > > > >   }
> > > > > >
> > > > > Ok.
> > > > >
> > > > > > > > +        Status = ProgramPciFeatures (RootBridge);
> > > > > > 10. ProgramPcieFeatures()?
> > > > > >
> > > > > OK
> > > > >
> > > > > > > > +
> > > > > > > > +  if (Str != NULL) {
> > > > > > > > +    FreePool (Str);
> > > > > > > > +  }
> > > > > >
> > > > > > 11. OK the Str is freed here because Str is needed for other
> > > > > > debug
> > > > > messages
> > > > > > inside the function.
> > > > > >
> > > > > Yes
> > > > >
> > > > > > > > +  //
> > > > > > > > +  // mark this root bridge as PCI features configuration
> > > > > > > > +complete, and no new
> > > > > > > > +  // enumeration is required
> > > > > > > > +  //
> > > > > > > > +  AddRootBridgeInPciFeaturesConfigCompletionList
> > > > > > > > +(RootBridge, FALSE);
> > > > > >
> > > > > > 12. Not needed.
> > > > > >
> > > > > ok, after incorporating the logic of gFullEnumeration it won't
> > > > > be required
> > > > >
> > > > > > > > +_PRIMARY_ROOT_PORT_NODE {
> > > > > >
> > > > > > > > +  //
> > > > > > > > +  // Signature header
> > > > > > > > +  //
> > > > > > > > +  UINT32                                    Signature;
> > > > > > > > +  //
> > > > > > > > +  // linked list pointers to next node
> > > > > > > > +  //
> > > > > > > > +  LIST_ENTRY                                NeighborRootPort;
> > > > > > > > +  //
> > > > > > > > +  // pointer to PCI_IO_DEVICE of the primary PCI
> > > > > > > > +Controller device
> > > > > > > > +  //
> > > > > > > > +  EFI_DEVICE_PATH_PROTOCOL
> *RootPortDevicePath;
> > > > > > > > +  //
> > > > > > > > +  // pointer to the corresponding PCI feature
> > > > > > > > +configuration Table node
> > > > > > > > +  // all the child PCI devices of the controller are
> > > > > > > > +aligned based on this table
> > > > > > > > +  //
> > > > > > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > > > *OtherPciFeaturesConfigurationTable;
> > > > > > > > +};
> > > > > >
> > > > > > 13. Can you add the
> OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > field
> > > > > to
> > > > > > PCI_IO_DEVICE structure?
> > > > > > So this structure PRIMARY_ROOT_PORT_NODE is not needed.
> > > > > >
> > > > > I think it is better to maintain separately as this
> > > > > configuration table is confined to a group of PCI devices and
> > > > > for the RCiEP it is not applicable hence not required. Moreover,
> > > > > I am maintaining a variable for each PCIe feature in the
> > > > > PCI_IO_DEVICE; perhaps I can
> > > consider having just pointer of it....
> > > > >
> > > > > > > > +struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
> > > > > > 14. This structure is not needed if using gFullEnumeration.
> > > > > Yes.
> > > >
> > > > 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
  2020-03-17  7:20                 ` Javeed, Ashraf
@ 2020-03-17 15:36                   ` Ni, Ray
  2020-04-20 13:22                     ` Javeed, Ashraf
  0 siblings, 1 reply; 51+ messages in thread
From: Ni, Ray @ 2020-03-17 15:36 UTC (permalink / raw)
  To: Javeed, Ashraf, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

Ashraf,
Thank you for the prompt response!

My response in below.
(I removed some earlier conversations, but the context is still kept.)

> > I take it as an agree of using the global AUTO. Thanks for that.
> Please note that there is another request of "Do not touch", and I am still contemplating whether both AUTO and
> DO_NOT_TOUCH options could be applicable to all the PCIe features or not. It could be possible to take AUTO for some of
> them and DO_NOT_TOUCH for others. Need to consider each PCIe feature separately for both these options.


I think we are basically aligned on this.
I agree that each PCIe feature should have clear statement about how to interpret AUTO and DO_NOT_TOUCH.
DO_NOT_TOUCH in my code change is NOT_APPLICABLE.
If you check some of the features I already implemented, the comments say clearly what AUTO and NOT_APPLICABLE mean
for that specific feature.
Looking forward to your comments on how to interpret AUTO and NOT_APPLICABLE for each PCIe feature.

> > Supposing a root bridge contains 1 RCiEP and two root ports, the
> > implementation ensures there will be 3 separate contexts for each. As you
> > can see, every time the code starts enumeration from a RCiEP or a root
> > port, a new Context[] is setup. Context[i] is associated with the feature _i_.
> >
> I realize now, that there are 3 nested for-loops in the EnumerateRootBridgePcieFeatures(), the first one enables the
> processing of first level nodes of the Root Bridge instance, and in this way the context[i] used for each node will be valid as
> it covers each node's hierarchy.

I think we are aligned on this.

> >
> > The level N and N+1 is needed for AtomicOp or Ltr feature (which I need to
> > go back to check the code).
> > I want to avoid the individual feature scan/program routine checks device's
> > parent/children.
> > I understand that in PCIE spec, a switch consists of an upstream port and
> > several downstream ports.
> > It means a switch populates a bridge which connects to the upstream and
> > several bridges under the upstream bridge which connect to the
> > downstream.
> > But from software perspective, I don't think we should care about that.
> > Maybe I am wrong. Can you please give a real example that treating in my
> > way would cause some issues?
> >
> Let just say we have PCIe switch connected to Root Port on a host, and it has 2 downstream ports, each connected to one
> Endpoint device each. Platform has selected to enable LTR for second downstream port's endpoint device, not both. As per
> your code logic of LTR, where you use the N and N+1 to compare between the parent and child, will not be applicable if
> you use the same condition to check downstream port (N+1), and its parent upstream port, because N would be the
> Endpoint device of first downstream port of the PCIe switch and not its upstream port.
> Root Port ->					1|0|0
> Switch upstream port ->				2|0|0 (M-1)
> Switch downstream ports ->	3|0|0,(M)		5|0|0 (N (=M+2))
> Endpoint devices ->		4|0|0 (M+1)		6|0|0 (N+1 (=M+3))
> The level+1 logic when the EnumeratePcieDevices() is called recursively, will result in one value greater than the Endpoint
> device for the second downstream port.

The level value in my code will be:
Root Port ->					1|0|0 (level 0)
Switch upstream port ->				2|0|0 (level 1)
Switch downstream ports ->	3|0|0,(level 2)		5|0|0,(level 2)
Endpoint devices ->		4|0|0,(level 3)		6|0|0,(level 3)

Level of device 5|0|0 is still 2, not 4.

I also did the unit test to ensure the LTR feature logic is good.

For below device hierarchy with LTR enabled in 5/0/0 and 11/0/0, disabled in 9/0/0
The LTR setting for upstream bridges should be as following:
                    0/4/0[LTR:1]
  2/0/0[1]  |       2/1/0[1]         | 2/2/0[0]
  3/0/0[1]  |       7/0/0[1]
  4/0/0[1]  |       8/0/0[1]
  5/0/0[1]  | 9/0/0[0]   9/1/0[1]
                         10/0/0[1]
                         11/0/0[1]

The unit test code is in commit "Test case for LTR".

> 
> > >
> > > I liked the Pre & Post order flag that is used to processing parent-to-child
> > vs. child-to-parent nodes.
> >
> > Actually I didn't have this flag in the first version of my code change. But
> > later I found it's needed for some features like LTR which needs to be
> > programmed from rootbridge to endpoint according to spec.
> >
> >
> > > You are calling the first
> > > and last features as fakes, when you actually parse all the nodes for
> > > the GetDevicePolicy() and NotifyDeviceState(); to me it is actually an
> > > un-named phase where all the nodes are queried or informed to the
> > platform; that seems fine to save the NULL on the mPcieFeatures[] table.
> >
> > Yes I put GetDevicePolicy() and NotifyDeviceState() in the feature array in
> > my first version of code. And later I called the two separately for better
> > code readability. But it was my fault that I didn't update the commit
> > message. It caused confusion to you.
> >
> > >
> > > Thanks
> > > Ashraf
> > >
> > > > -----Original Message-----
> > > > From: Ni, Ray <ray.ni@intel.com>
> > > > Sent: Thursday, March 5, 2020 7:43 PM
> > > > To: devel@edk2.groups.io; Ni, Ray <ray.ni@intel.com>; Javeed, Ashraf
> > > > <ashraf.javeed@intel.com>
> > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > <hao.a.wu@intel.com>
> > > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > > > 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > >
> > > > Ashraf,
> > > > I think it might be better to describe my review comments with code
> > > > implementation.
> > > > Can you please check this branch where I did some modification based
> > > > on your code?
> > > > https://github.com/niruiyu/edk2/tree/pci/pcie2
> > > >
> > > > Let's firstly align on the feature initialization framework
> > implementation.
> > > > To be specific, this commit:
> > > > MdeModulePkg/PciBus: Add the framework to init PCIE features
> > > >
> > https://github.com/niruiyu/edk2/commit/9fb9a3dcef06de98a76825e2fc0
> > > > 7167446ee6fd9
> > > >
> > > > Thanks,
> > > > Ray
> > > >
> > > > > -----Original Message-----
> > > > > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of
> > Ni,
> > > > Ray
> > > > > Sent: Thursday, December 19, 2019 1:49 PM
> > > > > To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > <hao.a.wu@intel.com>
> > > > > Subject: Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > > > > 05/12]
> > > > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > > >
> > > > > After I reviewed the patch of enabling MaxPayloadSize,
> > > > > MaxReadReqSize and more PCIE features, I can now understand the
> > > > > phases more than earlier.
> > > > >
> > > > > Your patch proposed five phases:
> > > > >   //
> > > > >   // 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
> > > > >
> > > > >
> > > > > I have several comments to the five phases.
> > > > > 1. Scan phase is not do the scanning but creates a list to hold
> > > > > all root ports under the root bridge.
> > > > > 2. Root ports collection is not required by all of the features,
> > > > > only by MPS and MRRS.
> > > > > But the collection always happens even when platform doesn't
> > > > > require PciBus to initialize MPS or MRRS.
> > > > > 3. GetDevicePolicy phase is not just call the GetDevicePolicy for
> > > > > each device. It also reads the PCIE configuration space to get the
> > > > > device's feature related capabilities, for some of the features.
> > > > >
> > > > > With that, I propose to define 4 phases:
> > > > > 1. Initialize phase
> > > > > This phase is similar to your Scan phase.
> > > > > For some features, this phase does nothing.
> > > > > For MPS and MRRS, this phase creates a list holding all root ports.
> > > > >
> > > > > 2. Scan phase
> > > > > This phase is similar to your GetDevicePolicy phase.
> > > > > For some features, this phase needs nothing do to.
> > > > > For MPS and MRRS, this phase scan all devices and get the aligned
> > > > > value of MPS or MRRS.
> > > > >
> > > > > 3. Program phase or Configuration phase This phase is similar to
> > > > > your Configuration phase.
> > > > > The Setup phase can be merged to this phase.
> > > > >
> > > > > 4. Finalize phase.
> > > > > This phase is similar to your ConfigurationComplete phase.
> > > > > This phase frees the resources occupied/allocated in Initialize phase.
> > > > > For some of the features, this phase may do nothing.
> > > > >
> > > > > Each feature needs to provide function pointers for each phase and
> > > > > NULL means the feature doesn't need to do anything in the specific
> > > > > phase.
> > > > > With that, we can define a structure:
> > > > > Typedef struct {
> > > > >   BOOLEAN                          Enable;
> > > > >   PCIE_FEATURE_INITILAIZE Initialize;
> > > > >   PCIE_FEATURE_SCAN  Scan;
> > > > >   PCIE_FEATURE_PROGRAM Program;
> > > > >   PCIE_FEATURE_FINALIZE Finalize;
> > > > > } PCIE_FEATURE_ENTRY;
> > > > >
> > > > > With that, we can define a module level global variable:
> > > > > PCIE_FEATURE_ENTRY mPcieFeatures[] = {
> > > > >   { TRUE, MaxPayloadInitialize, MaxPayloadScan, MaxPayloadProgram,
> > > > > MaxPayloadFinalize},
> > > > >   { TRUE, MaxReadRequestInitialize, MaxReadRequestScan,
> > > > > MaxReadRequestProgram, MaxReadRequestFinalize},
> > > > >   { TRUE, NULL, NULL, RelaxOrderProgram, NULL},
> > > > >   { TRUE, NULL, CompletionTimeoutScan, CompletionTimeoutProgram,
> > > > NULL },
> > > > >   ...
> > > > > };
> > > > >
> > > > > PCIE_FEATURE_ENTRY.Enable can be set to FALSE according to the
> > > > > platform policy.
> > > > >
> > > > > The enable of PCIE features can be written as a feature agnostic for-
> > loop.
> > > > > This can make the new feature enabling code easy to add and review.
> > > > >
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Javeed, Ashraf <ashraf.javeed@intel.com>
> > > > > > Sent: Wednesday, December 18, 2019 3:14 PM
> > > > > > To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> > > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > > <hao.a.wu@intel.com>
> > > > > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2
> > PATCH
> > > > > > 05/12]
> > > > > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > > > >
> > > > > > Thanks for the review, Ray!
> > > > > > My response in line
> > > > > >
> > > > > > > -----Original Message-----
> > > > > > > From: Ni, Ray <ray.ni@intel.com>
> > > > > > > Sent: Tuesday, December 17, 2019 5:26 PM
> > > > > > > To: Javeed, Ashraf <ashraf.javeed@intel.com>;
> > > > > > > devel@edk2.groups.io
> > > > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > > > <hao.a.wu@intel.com>
> > > > > > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2
> > > > > > > PATCH
> > > > > > 05/12]
> > > > > > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > > > > >
> > > > > > > Please check comments below.
> > > > > > > I may have more comments regarding to the four phases after I
> > > > > > > finish
> > > > > > review of
> > > > > > > further patches.
> > > > > > >
> > > > > > > Besides the comments below, I have a general comments to the
> > > > > > > debug
> > > > > > > message: can you please review the existing debug message in
> > > > > > > the PciBus
> > > > > > driver
> > > > > > > and make sure your newly added debug message aligns to
> > > > > > > existing
> > > > style.
> > > > > > And try
> > > > > > > to use less lines of debug messages with still enough debug
> > > > information.
> > > > > > Ok, will look into that.
> > > > > >
> > > > > > >
> > > > > > > > > +PRIMARY_ROOT_PORT_NODE
> > > > *mPrimaryRootPortList;
> > > > > > > > > +
> > > > > > > > > +/**
> > > > > > > > > +  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;
> > > > > > >
> > > > > > > 1. Please follow existing linked list usage style. The first
> > > > > > > node in the list is an empty header node.
> > > > > > >
> > > > > > > LIST_ENTRY   mPrimaryRootPortList;
> > > > > > > LIST_ENTRY   mPciFeaturesConfigurationCompletionList;
> > > > > > >
> > > > > > Ok, will make the change when I incorporate the ECR 0.75 or
> > > > > > greater
> > > > version.
> > > > > >
> > > > > > > > > +BOOLEAN
> > > > > > > > > +CheckPciFeatureConfigurationRecordExist (
> > > > > > > > > +  IN  PCI_IO_DEVICE                             *RootBridge,
> > > > > > > > > +  OUT PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > > > > > > +**PciFeatureConfigRecord
> > > > > > > > > +  )
> > > > > > >
> > > > > > > 2. Is this function to check whether the PCIE features under a
> > > > > > > root bridge is already initialized?
> > > > > > > Can you use the existing variable gFullEnumeration?
> > > > > > > The variable is set to TRUE when the enumeration is done to a
> > > > > > > host bridge
> > > > > > in the
> > > > > > > first time.
> > > > > > > By using gFullEnumeration, the entire function is not needed.
> > > > > > >
> > > > > > Ok, will look into this.
> > > > > >
> > > > > > > > > +EFI_STATUS
> > AddRootBridgeInPciFeaturesConfigCompletionList (
> > > > > > > > > +  IN PCI_IO_DEVICE          *RootBridge,
> > > > > > > > > +  IN BOOLEAN                ReEnumerationRequired
> > > > > > > > > +  )
> > > > > > >
> > > > > > > 3. Same question as #2. I think by using gFullEnumeration,
> > > > > > > this function is
> > > > > > not
> > > > > > > needed.
> > > > > > >
> > > > > > OK
> > > > > >
> > > > > > >
> > > > > > > > > +BOOLEAN
> > > > > > > > > +IsPciRootPortEmpty (
> > > > > > > > > +  IN  PCI_IO_DEVICE                           *PciDevice
> > > > > > > > > +  )
> > > > > > >
> > > > > > > 4. Please use IsListEmpty() directly from callers and remove
> > > > > > > this
> > > > function.
> > > > > > >
> > > > > > Will consider this.
> > > > > >
> > > > > > > > > +**/
> > > > > > > > > +EFI_STATUS
> > > > > > > > > +EnumerateOtherPciFeatures (
> > > > > > >
> > > > > > > 5. Can it be "EnumeratePcieFeatures"?
> > > > > > >
> > > > > > Yes, with the change to ECR 0.75, this routine name shall be
> > changed.
> > > > > >
> > > > > > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > > > > > > +  )
> > > > > > > > > +{
> > > > > > > > > +  EFI_STATUS            Status;
> > > > > > > > > +  UINTN                 OtherPciFeatureConfigPhase;
> > > > > > > > > +
> > > > > > > > > +  //
> > > > > > > > > +  // check on PCI features configuration is complete and
> > > > > > > > > + re-enumeration is required  //  if
> > > > > > > > > + (!CheckPciFeaturesConfigurationRequired
> > > > > > > > > + (RootBridge)) {
> > > > > > > > > +    return EFI_ALREADY_STARTED;  }
> > > > > > > > > +
> > > > > > >  > > +  CHAR16                *Str;
> > > > > > > > > +  Str = ConvertDevicePathToText (
> > > > > > > > > +          DevicePathFromHandle (RootBridge->Handle),
> > > > > > > > > +          FALSE,
> > > > > > > > > +          FALSE
> > > > > > > > > +        );
> > > > > > > > > +  DEBUG ((DEBUG_INFO, "Enumerating PCI features for Root
> > > > > > > > > + Bridge %s\n", Str != NULL ? Str : L""));
> > > > > > >
> > > > > > > 6. Please use DEBUG_CODE macro to include
> > > > > > > ConvertDevicePathToText()
> > > > > > and
> > > > > > > DEBUG().
> > > > > > > Please remember to call FreePool().
> > > > > > >
> > > > > > Ok, will can under DEBUG_CODE, and free pool is called in the
> > > > > > end
> > > > > >
> > > > > > > > > +
> > > > > > > > > +  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);
> > > > > > >
> > > > > > > 7. How about "RecordPciRootPorts (RootBridge)"? The "Bridges"
> > > > > > > suffix is a
> > > > > > bit
> > > > > > > confusing.
> > > > > > >
> > > > > > Fine, will change.
> > > > > >
> > > > > > > > > +      case  PciFeatureGetDevicePolicy:
> > > > > > > > > +      case  PciFeatureSetupPhase:
> > > > > > >
> > > > > > > 8. In SetupPciFeatures(), why do you need to call DeviceExist()?
> > > > > > > Did you see any case that a device is detected in the
> > > > > > > beginning of PciBus
> > > > > > scan
> > > > > > > but is hidden when calling SetupPciFeatures()?
> > > > > > >
> > > > > > Yes, that is the case; device detected during the beginning of
> > > > > > PciBus scan appears to be hidden by the platform drivers, since
> > > > > > numerous legacy callbacks are initiated at different phase of
> > > > > > PCI enumeration to the PCI Host Bridge, and PciPlatform drivers.
> > > > > > This can be avoided if the PciBus driver is enhanced to check
> > > > > > for PCI device existence before the publication of the PCI IO
> > > > > > Protocol, and removal of the PCI_IO_DEVICE instance from the
> > linked list.
> > > > > >
> > > > > > > 9. In GetPciFeaturesConfigurationTable() when checking whether
> > > > > > > a PCI
> > > > > > device
> > > > > > > belongs to a root port, we can use below simpler logic:
> > > > > > >   SizeOfPciDevicePath = GetDevicePathSize (PciDevicePath);
> > > > > > >   SizeOfRootPortDevicePath = GetDevicePathSize (RootPortPath);
> > > > > > >   if ((SizeOfRootPortDevicePath < SizeOfPciDevicePath) &&
> > > > > > >       CompareMem (PciDevicePath, RootPortPath,
> > > > > > SizeOfRootPortDevicePath -
> > > > > > > END_DEVICE_PATH_LENGTH) == 0)) {
> > > > > > >     // PCI device belongs to the root port.
> > > > > > >   }
> > > > > > >
> > > > > > Ok.
> > > > > >
> > > > > > > > > +        Status = ProgramPciFeatures (RootBridge);
> > > > > > > 10. ProgramPcieFeatures()?
> > > > > > >
> > > > > > OK
> > > > > >
> > > > > > > > > +
> > > > > > > > > +  if (Str != NULL) {
> > > > > > > > > +    FreePool (Str);
> > > > > > > > > +  }
> > > > > > >
> > > > > > > 11. OK the Str is freed here because Str is needed for other
> > > > > > > debug
> > > > > > messages
> > > > > > > inside the function.
> > > > > > >
> > > > > > Yes
> > > > > >
> > > > > > > > > +  //
> > > > > > > > > +  // mark this root bridge as PCI features configuration
> > > > > > > > > +complete, and no new
> > > > > > > > > +  // enumeration is required
> > > > > > > > > +  //
> > > > > > > > > +  AddRootBridgeInPciFeaturesConfigCompletionList
> > > > > > > > > +(RootBridge, FALSE);
> > > > > > >
> > > > > > > 12. Not needed.
> > > > > > >
> > > > > > ok, after incorporating the logic of gFullEnumeration it won't
> > > > > > be required
> > > > > >
> > > > > > > > > +_PRIMARY_ROOT_PORT_NODE {
> > > > > > >
> > > > > > > > > +  //
> > > > > > > > > +  // Signature header
> > > > > > > > > +  //
> > > > > > > > > +  UINT32                                    Signature;
> > > > > > > > > +  //
> > > > > > > > > +  // linked list pointers to next node
> > > > > > > > > +  //
> > > > > > > > > +  LIST_ENTRY                                NeighborRootPort;
> > > > > > > > > +  //
> > > > > > > > > +  // pointer to PCI_IO_DEVICE of the primary PCI
> > > > > > > > > +Controller device
> > > > > > > > > +  //
> > > > > > > > > +  EFI_DEVICE_PATH_PROTOCOL
> > *RootPortDevicePath;
> > > > > > > > > +  //
> > > > > > > > > +  // pointer to the corresponding PCI feature
> > > > > > > > > +configuration Table node
> > > > > > > > > +  // all the child PCI devices of the controller are
> > > > > > > > > +aligned based on this table
> > > > > > > > > +  //
> > > > > > > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > > > > *OtherPciFeaturesConfigurationTable;
> > > > > > > > > +};
> > > > > > >
> > > > > > > 13. Can you add the
> > OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > field
> > > > > > to
> > > > > > > PCI_IO_DEVICE structure?
> > > > > > > So this structure PRIMARY_ROOT_PORT_NODE is not needed.
> > > > > > >
> > > > > > I think it is better to maintain separately as this
> > > > > > configuration table is confined to a group of PCI devices and
> > > > > > for the RCiEP it is not applicable hence not required. Moreover,
> > > > > > I am maintaining a variable for each PCIe feature in the
> > > > > > PCI_IO_DEVICE; perhaps I can
> > > > consider having just pointer of it....
> > > > > >
> > > > > > > > > +struct _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
> > > > > > > 14. This structure is not needed if using gFullEnumeration.
> > > > > > Yes.
> > > > >
> > > > > 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
  2020-03-17 15:36                   ` Ni, Ray
@ 2020-04-20 13:22                     ` Javeed, Ashraf
  2020-04-21  6:03                       ` Javeed, Ashraf
  0 siblings, 1 reply; 51+ messages in thread
From: Javeed, Ashraf @ 2020-04-20 13:22 UTC (permalink / raw)
  To: Ni, Ray, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A, Javeed, Ashraf

Ray,
Sorry for late response as I got into other priorities. Let's try to finish this ASAP.
Certainly the implementation of yours has reduced the code size in great deal by deprecating the EFI encodings for the PCIe features, and using the actual HW values along with the global definition of AUTO and NOT_APPLICABLE (as an alias to DO_NOT_TOUCH). I am concerned that lot of explanation in the text of the PCI Express Protocol has to be provided about the rules that platform FW developer has to follow w.r.t. AUTO and DO_NOT_TOUCH in the GetDevicePolicy(); that needs to be published in the PI Specification. I shall take your implementation and add the other 3 PCIe features that I had implemented (ExtendedTag, Aspm, CommonClockConfiguration) into this scheme, and also provide how these global options rules can be defined for the other non-implemented PCIe features.
However, I have other suggestions/corrections for the present 7 PCIe features implementation, which I want to discuss by highlighting the platform policy of AUTO and DO_NOT_DISTURB.

(1) MaxPayloadSize:- This feature requires aligning all the PCI devices in the hierarchy to have a common value. (The device policy by platform shall be used to align with all the devices in hierarchy based on their capability, thus value less than capability shall result in all devices in hierarchy supporting that value in capability to be programmed).
	(a) AUTO: The DeviceCapability.MaxPayloadSize value is considered while scan all the nodes in the hierarchy
	(b) DO_NOT_TOUCH: Should be considered as invalid value to skip for this feature. Two options in this scenario...
		(i) The PciBusDxe shall use this option to force the HW default value of 128B
		(ii) Behave same as AUTO.
	I vote for option (i) above.

(2) MaxReadReqSize:- Does not need all the devices in hierarchy to be align to common value. However, the spec imposes that for an isochronous configured device its memory read request should be equal to MayPayloadSize; thus I accept your implementation since determining whether that device in Isochronous mode is beyond the scope of PciBusDxe
	(a) AUTO: MaxReadReqSize = MaxPayloadSize; shall cover the device configured in Isochronous case.
	(b) DO_NOT_TOUCH: skip programming the DeviceControl register of the device

(3) RelaxOrdering:- Specific to device to enable or disable; does not require any coherency with all the devices in the hierarchy
	(a) AUTO: device initialization is skipped
	(b) DO_NOT_TOUCH: device initialization is skipped

(4) NoSnoop:- Specific to device to enable or disable; does not require any coherency with all the devices in the hierarchy
	(a) AUTO: device initialization is skipped
	(b) DO_NOT_TOUCH: device initialization is skipped

(5) CompletionTimeout:-  The range and detection mechanism disable can be set specifically for any device; does not require to be aligned with all devices in the hierarchy
	(a) AUTO: your implementation ignores it (same as do not touch); I propose that platform can provide this option to set the DeviceControl2.CompletionTimeoutValue as per its high range value of DeviceCapability2.CompletionTimeoutRangesSupported, ignoring the CompletionTimeoutDisableSupported. For example; if the DeviceCapability2 supports Ranges A, B, C and D; than its DeviceControl2.CompletionTimeoutValue can be programmed to 1110b (17s to 64s) for higher subrange.
	(b) DO_NOT_TOUCH: device initialization is skipped
	Your implementation about the device policy from platform appears OK to me.

(6) Ltr: As per PCIe specification, the LTR capability is provided for all the PCI devices, disabled by default, and if LTR needs to be enabled for Endpoint device than all the in-between component from Root Port to Endpoint needs to be enabled, and it is not required that all Endpoints have to be LTR enabled.
	(a) AUTO: as per your implementation, this option is ignored as invalid, and overwritten with its child device and if no valid for child device than device initialization is skipped
	(b) DO_NOT_TOUCH: as per your implementation, this option is ignored as invalid. and overwritten with its child device and if no valid for child device than device initialization is skipped
	Why does your implementation consider changing only the parent N as per its child N+1, and not vice versa? If platform only updates the Root port (RP) and not the Endpoint device than this implementation only programs the RP, right?
	In real scenario, the platform FW does not provide the policy for PCIe Endpoint devices mounted on the PCIe slots since those policies are statically defined to the fixed components of the chip. Thus, platform expects enabling the PCIe Root Port LTR mechanism, in hope that its valid PCIe Endpoint device gets enabled if all the devices are capable of LTR mechanism.
	I propose, even if platform provides one device to be LTR enable in the path from Root Port to Endpoint device, than PciBusDxe can enable all the devices in the path if all are LTR capable. This shall be also for Switch with multiple downstream ports with each port connected to independent Endpoint devices, if platform provide LTR enable to Root Port than enable for each path of devices if the downstream port's Endpoint device is LTR capable. If any one downstream port's Endpoint device is not capable than it need not set for that device.

(7) AtomicOp: As per PCIe specification, the DeviceControl2 register provides the AtomicOp Requester Enable bit (6) and blocking of AtomicOp request bit (7) for the Port device.
	The AtomicOp requester capability determination is out of scope, hence it can be just relied on platform policy request. However, the blocking AtomicOp request on the port device depends on the Device Routing capability bit defined in the DeviceCapability2 register.
	(a) AUTO: device initialization is skipped
	(b) DO_NOT_TOUCH: device initialization is skipped
	I think the change required in this implementation is the check for the Routing Capability to enable the blocking of AtomicOp request for the port device; do you agree?

Thanks
Ashraf

> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Tuesday, March 17, 2020 9:07 PM
> To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> <hao.a.wu@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
> 
> Ashraf,
> Thank you for the prompt response!
> 
> My response in below.
> (I removed some earlier conversations, but the context is still kept.)
> 
> > > I take it as an agree of using the global AUTO. Thanks for that.
> > Please note that there is another request of "Do not touch", and I am
> > still contemplating whether both AUTO and DO_NOT_TOUCH options
> could
> > be applicable to all the PCIe features or not. It could be possible to take
> AUTO for some of them and DO_NOT_TOUCH for others. Need to consider
> each PCIe feature separately for both these options.
> 
> 
> I think we are basically aligned on this.
> I agree that each PCIe feature should have clear statement about how to
> interpret AUTO and DO_NOT_TOUCH.
> DO_NOT_TOUCH in my code change is NOT_APPLICABLE.
> If you check some of the features I already implemented, the comments say
> clearly what AUTO and NOT_APPLICABLE mean for that specific feature.
> Looking forward to your comments on how to interpret AUTO and
> NOT_APPLICABLE for each PCIe feature.
> 
> > > Supposing a root bridge contains 1 RCiEP and two root ports, the
> > > implementation ensures there will be 3 separate contexts for each.
> > > As you can see, every time the code starts enumeration from a RCiEP
> > > or a root port, a new Context[] is setup. Context[i] is associated with the
> feature _i_.
> > >
> > I realize now, that there are 3 nested for-loops in the
> > EnumerateRootBridgePcieFeatures(), the first one enables the
> > processing of first level nodes of the Root Bridge instance, and in this way
> the context[i] used for each node will be valid as it covers each node's
> hierarchy.
> 
> I think we are aligned on this.
> 
> > >
> > > The level N and N+1 is needed for AtomicOp or Ltr feature (which I
> > > need to go back to check the code).
> > > I want to avoid the individual feature scan/program routine checks
> > > device's parent/children.
> > > I understand that in PCIE spec, a switch consists of an upstream
> > > port and several downstream ports.
> > > It means a switch populates a bridge which connects to the upstream
> > > and several bridges under the upstream bridge which connect to the
> > > downstream.
> > > But from software perspective, I don't think we should care about that.
> > > Maybe I am wrong. Can you please give a real example that treating
> > > in my way would cause some issues?
> > >
> > Let just say we have PCIe switch connected to Root Port on a host, and
> > it has 2 downstream ports, each connected to one Endpoint device each.
> > Platform has selected to enable LTR for second downstream port's
> > endpoint device, not both. As per your code logic of LTR, where you
> > use the N and N+1 to compare between the parent and child, will not be
> applicable if you use the same condition to check downstream port (N+1),
> and its parent upstream port, because N would be the Endpoint device of
> first downstream port of the PCIe switch and not its upstream port.
> > Root Port ->					1|0|0
> > Switch upstream port ->				2|0|0 (M-1)
> > Switch downstream ports ->	3|0|0,(M)		5|0|0 (N (=M+2))
> > Endpoint devices ->		4|0|0 (M+1)		6|0|0 (N+1 (=M+3))
> > The level+1 logic when the EnumeratePcieDevices() is called
> > recursively, will result in one value greater than the Endpoint device for
> the second downstream port.
> 
> The level value in my code will be:
> Root Port ->					1|0|0 (level 0)
> Switch upstream port ->				2|0|0 (level 1)
> Switch downstream ports ->	3|0|0,(level 2)		5|0|0,(level 2)
> Endpoint devices ->		4|0|0,(level 3)		6|0|0,(level 3)
> 
> Level of device 5|0|0 is still 2, not 4.
> 
> I also did the unit test to ensure the LTR feature logic is good.
> 
> For below device hierarchy with LTR enabled in 5/0/0 and 11/0/0, disabled
> in 9/0/0 The LTR setting for upstream bridges should be as following:
>                     0/4/0[LTR:1]
>   2/0/0[1]  |       2/1/0[1]         | 2/2/0[0]
>   3/0/0[1]  |       7/0/0[1]
>   4/0/0[1]  |       8/0/0[1]
>   5/0/0[1]  | 9/0/0[0]   9/1/0[1]
>                          10/0/0[1]
>                          11/0/0[1]
> 
> The unit test code is in commit "Test case for LTR".
> 
> >
> > > >
> > > > I liked the Pre & Post order flag that is used to processing
> > > > parent-to-child
> > > vs. child-to-parent nodes.
> > >
> > > Actually I didn't have this flag in the first version of my code
> > > change. But later I found it's needed for some features like LTR
> > > which needs to be programmed from rootbridge to endpoint according
> to spec.
> > >
> > >
> > > > You are calling the first
> > > > and last features as fakes, when you actually parse all the nodes
> > > > for the GetDevicePolicy() and NotifyDeviceState(); to me it is
> > > > actually an un-named phase where all the nodes are queried or
> > > > informed to the
> > > platform; that seems fine to save the NULL on the mPcieFeatures[]
> table.
> > >
> > > Yes I put GetDevicePolicy() and NotifyDeviceState() in the feature
> > > array in my first version of code. And later I called the two
> > > separately for better code readability. But it was my fault that I
> > > didn't update the commit message. It caused confusion to you.
> > >
> > > >
> > > > Thanks
> > > > Ashraf
> > > >
> > > > > -----Original Message-----
> > > > > From: Ni, Ray <ray.ni@intel.com>
> > > > > Sent: Thursday, March 5, 2020 7:43 PM
> > > > > To: devel@edk2.groups.io; Ni, Ray <ray.ni@intel.com>; Javeed,
> > > > > Ashraf <ashraf.javeed@intel.com>
> > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > <hao.a.wu@intel.com>
> > > > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2
> PATCH
> > > > > 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > > >
> > > > > Ashraf,
> > > > > I think it might be better to describe my review comments with
> > > > > code implementation.
> > > > > Can you please check this branch where I did some modification
> > > > > based on your code?
> > > > > https://github.com/niruiyu/edk2/tree/pci/pcie2
> > > > >
> > > > > Let's firstly align on the feature initialization framework
> > > implementation.
> > > > > To be specific, this commit:
> > > > > MdeModulePkg/PciBus: Add the framework to init PCIE features
> > > > >
> > >
> https://github.com/niruiyu/edk2/commit/9fb9a3dcef06de98a76825e2fc0
> > > > > 7167446ee6fd9
> > > > >
> > > > > Thanks,
> > > > > Ray
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf
> Of
> > > Ni,
> > > > > Ray
> > > > > > Sent: Thursday, December 19, 2019 1:49 PM
> > > > > > To: Javeed, Ashraf <ashraf.javeed@intel.com>;
> > > > > > devel@edk2.groups.io
> > > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > > <hao.a.wu@intel.com>
> > > > > > Subject: Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2
> > > > > > PATCH 05/12]
> > > > > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > > > >
> > > > > > After I reviewed the patch of enabling MaxPayloadSize,
> > > > > > MaxReadReqSize and more PCIE features, I can now understand
> > > > > > the phases more than earlier.
> > > > > >
> > > > > > Your patch proposed five phases:
> > > > > >   //
> > > > > >   // 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
> > > > > >
> > > > > >
> > > > > > I have several comments to the five phases.
> > > > > > 1. Scan phase is not do the scanning but creates a list to
> > > > > > hold all root ports under the root bridge.
> > > > > > 2. Root ports collection is not required by all of the
> > > > > > features, only by MPS and MRRS.
> > > > > > But the collection always happens even when platform doesn't
> > > > > > require PciBus to initialize MPS or MRRS.
> > > > > > 3. GetDevicePolicy phase is not just call the GetDevicePolicy
> > > > > > for each device. It also reads the PCIE configuration space to
> > > > > > get the device's feature related capabilities, for some of the
> features.
> > > > > >
> > > > > > With that, I propose to define 4 phases:
> > > > > > 1. Initialize phase
> > > > > > This phase is similar to your Scan phase.
> > > > > > For some features, this phase does nothing.
> > > > > > For MPS and MRRS, this phase creates a list holding all root ports.
> > > > > >
> > > > > > 2. Scan phase
> > > > > > This phase is similar to your GetDevicePolicy phase.
> > > > > > For some features, this phase needs nothing do to.
> > > > > > For MPS and MRRS, this phase scan all devices and get the
> > > > > > aligned value of MPS or MRRS.
> > > > > >
> > > > > > 3. Program phase or Configuration phase This phase is similar
> > > > > > to your Configuration phase.
> > > > > > The Setup phase can be merged to this phase.
> > > > > >
> > > > > > 4. Finalize phase.
> > > > > > This phase is similar to your ConfigurationComplete phase.
> > > > > > This phase frees the resources occupied/allocated in Initialize
> phase.
> > > > > > For some of the features, this phase may do nothing.
> > > > > >
> > > > > > Each feature needs to provide function pointers for each phase
> > > > > > and NULL means the feature doesn't need to do anything in the
> > > > > > specific phase.
> > > > > > With that, we can define a structure:
> > > > > > Typedef struct {
> > > > > >   BOOLEAN                          Enable;
> > > > > >   PCIE_FEATURE_INITILAIZE Initialize;
> > > > > >   PCIE_FEATURE_SCAN  Scan;
> > > > > >   PCIE_FEATURE_PROGRAM Program;
> > > > > >   PCIE_FEATURE_FINALIZE Finalize; } PCIE_FEATURE_ENTRY;
> > > > > >
> > > > > > With that, we can define a module level global variable:
> > > > > > PCIE_FEATURE_ENTRY mPcieFeatures[] = {
> > > > > >   { TRUE, MaxPayloadInitialize, MaxPayloadScan,
> > > > > > MaxPayloadProgram, MaxPayloadFinalize},
> > > > > >   { TRUE, MaxReadRequestInitialize, MaxReadRequestScan,
> > > > > > MaxReadRequestProgram, MaxReadRequestFinalize},
> > > > > >   { TRUE, NULL, NULL, RelaxOrderProgram, NULL},
> > > > > >   { TRUE, NULL, CompletionTimeoutScan,
> > > > > > CompletionTimeoutProgram,
> > > > > NULL },
> > > > > >   ...
> > > > > > };
> > > > > >
> > > > > > PCIE_FEATURE_ENTRY.Enable can be set to FALSE according to the
> > > > > > platform policy.
> > > > > >
> > > > > > The enable of PCIE features can be written as a feature
> > > > > > agnostic for-
> > > loop.
> > > > > > This can make the new feature enabling code easy to add and
> review.
> > > > > >
> > > > > >
> > > > > > > -----Original Message-----
> > > > > > > From: Javeed, Ashraf <ashraf.javeed@intel.com>
> > > > > > > Sent: Wednesday, December 18, 2019 3:14 PM
> > > > > > > To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> > > > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > > > <hao.a.wu@intel.com>
> > > > > > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2
> > > PATCH
> > > > > > > 05/12]
> > > > > > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > > > > >
> > > > > > > Thanks for the review, Ray!
> > > > > > > My response in line
> > > > > > >
> > > > > > > > -----Original Message-----
> > > > > > > > From: Ni, Ray <ray.ni@intel.com>
> > > > > > > > Sent: Tuesday, December 17, 2019 5:26 PM
> > > > > > > > To: Javeed, Ashraf <ashraf.javeed@intel.com>;
> > > > > > > > devel@edk2.groups.io
> > > > > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > > > > <hao.a.wu@intel.com>
> > > > > > > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2
> > > > > > > > PATCH
> > > > > > > 05/12]
> > > > > > > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > > > > > >
> > > > > > > > Please check comments below.
> > > > > > > > I may have more comments regarding to the four phases
> > > > > > > > after I finish
> > > > > > > review of
> > > > > > > > further patches.
> > > > > > > >
> > > > > > > > Besides the comments below, I have a general comments to
> > > > > > > > the debug
> > > > > > > > message: can you please review the existing debug message
> > > > > > > > in the PciBus
> > > > > > > driver
> > > > > > > > and make sure your newly added debug message aligns to
> > > > > > > > existing
> > > > > style.
> > > > > > > And try
> > > > > > > > to use less lines of debug messages with still enough
> > > > > > > > debug
> > > > > information.
> > > > > > > Ok, will look into that.
> > > > > > >
> > > > > > > >
> > > > > > > > > > +PRIMARY_ROOT_PORT_NODE
> > > > > *mPrimaryRootPortList;
> > > > > > > > > > +
> > > > > > > > > > +/**
> > > > > > > > > > +  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;
> > > > > > > >
> > > > > > > > 1. Please follow existing linked list usage style. The
> > > > > > > > first node in the list is an empty header node.
> > > > > > > >
> > > > > > > > LIST_ENTRY   mPrimaryRootPortList;
> > > > > > > > LIST_ENTRY   mPciFeaturesConfigurationCompletionList;
> > > > > > > >
> > > > > > > Ok, will make the change when I incorporate the ECR 0.75 or
> > > > > > > greater
> > > > > version.
> > > > > > >
> > > > > > > > > > +BOOLEAN
> > > > > > > > > > +CheckPciFeatureConfigurationRecordExist (
> > > > > > > > > > +  IN  PCI_IO_DEVICE                             *RootBridge,
> > > > > > > > > > +  OUT PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > > > > > > > +**PciFeatureConfigRecord
> > > > > > > > > > +  )
> > > > > > > >
> > > > > > > > 2. Is this function to check whether the PCIE features
> > > > > > > > under a root bridge is already initialized?
> > > > > > > > Can you use the existing variable gFullEnumeration?
> > > > > > > > The variable is set to TRUE when the enumeration is done
> > > > > > > > to a host bridge
> > > > > > > in the
> > > > > > > > first time.
> > > > > > > > By using gFullEnumeration, the entire function is not needed.
> > > > > > > >
> > > > > > > Ok, will look into this.
> > > > > > >
> > > > > > > > > > +EFI_STATUS
> > > AddRootBridgeInPciFeaturesConfigCompletionList (
> > > > > > > > > > +  IN PCI_IO_DEVICE          *RootBridge,
> > > > > > > > > > +  IN BOOLEAN                ReEnumerationRequired
> > > > > > > > > > +  )
> > > > > > > >
> > > > > > > > 3. Same question as #2. I think by using gFullEnumeration,
> > > > > > > > this function is
> > > > > > > not
> > > > > > > > needed.
> > > > > > > >
> > > > > > > OK
> > > > > > >
> > > > > > > >
> > > > > > > > > > +BOOLEAN
> > > > > > > > > > +IsPciRootPortEmpty (
> > > > > > > > > > +  IN  PCI_IO_DEVICE                           *PciDevice
> > > > > > > > > > +  )
> > > > > > > >
> > > > > > > > 4. Please use IsListEmpty() directly from callers and
> > > > > > > > remove this
> > > > > function.
> > > > > > > >
> > > > > > > Will consider this.
> > > > > > >
> > > > > > > > > > +**/
> > > > > > > > > > +EFI_STATUS
> > > > > > > > > > +EnumerateOtherPciFeatures (
> > > > > > > >
> > > > > > > > 5. Can it be "EnumeratePcieFeatures"?
> > > > > > > >
> > > > > > > Yes, with the change to ECR 0.75, this routine name shall be
> > > changed.
> > > > > > >
> > > > > > > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > > > > > > > +  )
> > > > > > > > > > +{
> > > > > > > > > > +  EFI_STATUS            Status;
> > > > > > > > > > +  UINTN                 OtherPciFeatureConfigPhase;
> > > > > > > > > > +
> > > > > > > > > > +  //
> > > > > > > > > > +  // check on PCI features configuration is complete
> > > > > > > > > > + and re-enumeration is required  //  if
> > > > > > > > > > + (!CheckPciFeaturesConfigurationRequired
> > > > > > > > > > + (RootBridge)) {
> > > > > > > > > > +    return EFI_ALREADY_STARTED;  }
> > > > > > > > > > +
> > > > > > > >  > > +  CHAR16                *Str;
> > > > > > > > > > +  Str = ConvertDevicePathToText (
> > > > > > > > > > +          DevicePathFromHandle (RootBridge->Handle),
> > > > > > > > > > +          FALSE,
> > > > > > > > > > +          FALSE
> > > > > > > > > > +        );
> > > > > > > > > > +  DEBUG ((DEBUG_INFO, "Enumerating PCI features for
> > > > > > > > > > + Root Bridge %s\n", Str != NULL ? Str : L""));
> > > > > > > >
> > > > > > > > 6. Please use DEBUG_CODE macro to include
> > > > > > > > ConvertDevicePathToText()
> > > > > > > and
> > > > > > > > DEBUG().
> > > > > > > > Please remember to call FreePool().
> > > > > > > >
> > > > > > > Ok, will can under DEBUG_CODE, and free pool is called in
> > > > > > > the end
> > > > > > >
> > > > > > > > > > +
> > > > > > > > > > +  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);
> > > > > > > >
> > > > > > > > 7. How about "RecordPciRootPorts (RootBridge)"? The
> "Bridges"
> > > > > > > > suffix is a
> > > > > > > bit
> > > > > > > > confusing.
> > > > > > > >
> > > > > > > Fine, will change.
> > > > > > >
> > > > > > > > > > +      case  PciFeatureGetDevicePolicy:
> > > > > > > > > > +      case  PciFeatureSetupPhase:
> > > > > > > >
> > > > > > > > 8. In SetupPciFeatures(), why do you need to call DeviceExist()?
> > > > > > > > Did you see any case that a device is detected in the
> > > > > > > > beginning of PciBus
> > > > > > > scan
> > > > > > > > but is hidden when calling SetupPciFeatures()?
> > > > > > > >
> > > > > > > Yes, that is the case; device detected during the beginning
> > > > > > > of PciBus scan appears to be hidden by the platform drivers,
> > > > > > > since numerous legacy callbacks are initiated at different
> > > > > > > phase of PCI enumeration to the PCI Host Bridge, and
> PciPlatform drivers.
> > > > > > > This can be avoided if the PciBus driver is enhanced to
> > > > > > > check for PCI device existence before the publication of the
> > > > > > > PCI IO Protocol, and removal of the PCI_IO_DEVICE instance
> > > > > > > from the
> > > linked list.
> > > > > > >
> > > > > > > > 9. In GetPciFeaturesConfigurationTable() when checking
> > > > > > > > whether a PCI
> > > > > > > device
> > > > > > > > belongs to a root port, we can use below simpler logic:
> > > > > > > >   SizeOfPciDevicePath = GetDevicePathSize (PciDevicePath);
> > > > > > > >   SizeOfRootPortDevicePath = GetDevicePathSize
> (RootPortPath);
> > > > > > > >   if ((SizeOfRootPortDevicePath < SizeOfPciDevicePath) &&
> > > > > > > >       CompareMem (PciDevicePath, RootPortPath,
> > > > > > > SizeOfRootPortDevicePath -
> > > > > > > > END_DEVICE_PATH_LENGTH) == 0)) {
> > > > > > > >     // PCI device belongs to the root port.
> > > > > > > >   }
> > > > > > > >
> > > > > > > Ok.
> > > > > > >
> > > > > > > > > > +        Status = ProgramPciFeatures (RootBridge);
> > > > > > > > 10. ProgramPcieFeatures()?
> > > > > > > >
> > > > > > > OK
> > > > > > >
> > > > > > > > > > +
> > > > > > > > > > +  if (Str != NULL) {
> > > > > > > > > > +    FreePool (Str);
> > > > > > > > > > +  }
> > > > > > > >
> > > > > > > > 11. OK the Str is freed here because Str is needed for
> > > > > > > > other debug
> > > > > > > messages
> > > > > > > > inside the function.
> > > > > > > >
> > > > > > > Yes
> > > > > > >
> > > > > > > > > > +  //
> > > > > > > > > > +  // mark this root bridge as PCI features
> > > > > > > > > > +configuration complete, and no new
> > > > > > > > > > +  // enumeration is required
> > > > > > > > > > +  //
> > > > > > > > > > +  AddRootBridgeInPciFeaturesConfigCompletionList
> > > > > > > > > > +(RootBridge, FALSE);
> > > > > > > >
> > > > > > > > 12. Not needed.
> > > > > > > >
> > > > > > > ok, after incorporating the logic of gFullEnumeration it
> > > > > > > won't be required
> > > > > > >
> > > > > > > > > > +_PRIMARY_ROOT_PORT_NODE {
> > > > > > > >
> > > > > > > > > > +  //
> > > > > > > > > > +  // Signature header
> > > > > > > > > > +  //
> > > > > > > > > > +  UINT32                                    Signature;
> > > > > > > > > > +  //
> > > > > > > > > > +  // linked list pointers to next node
> > > > > > > > > > +  //
> > > > > > > > > > +  LIST_ENTRY                                NeighborRootPort;
> > > > > > > > > > +  //
> > > > > > > > > > +  // pointer to PCI_IO_DEVICE of the primary PCI
> > > > > > > > > > +Controller device
> > > > > > > > > > +  //
> > > > > > > > > > +  EFI_DEVICE_PATH_PROTOCOL
> > > *RootPortDevicePath;
> > > > > > > > > > +  //
> > > > > > > > > > +  // pointer to the corresponding PCI feature
> > > > > > > > > > +configuration Table node
> > > > > > > > > > +  // all the child PCI devices of the controller are
> > > > > > > > > > +aligned based on this table
> > > > > > > > > > +  //
> > > > > > > > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > > > > > *OtherPciFeaturesConfigurationTable;
> > > > > > > > > > +};
> > > > > > > >
> > > > > > > > 13. Can you add the
> > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > field
> > > > > > > to
> > > > > > > > PCI_IO_DEVICE structure?
> > > > > > > > So this structure PRIMARY_ROOT_PORT_NODE is not needed.
> > > > > > > >
> > > > > > > I think it is better to maintain separately as this
> > > > > > > configuration table is confined to a group of PCI devices
> > > > > > > and for the RCiEP it is not applicable hence not required.
> > > > > > > Moreover, I am maintaining a variable for each PCIe feature
> > > > > > > in the PCI_IO_DEVICE; perhaps I can
> > > > > consider having just pointer of it....
> > > > > > >
> > > > > > > > > > +struct
> _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
> > > > > > > > 14. This structure is not needed if using gFullEnumeration.
> > > > > > > Yes.
> > > > > >
> > > > > > 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
  2020-04-20 13:22                     ` Javeed, Ashraf
@ 2020-04-21  6:03                       ` Javeed, Ashraf
  2020-04-21  6:22                         ` Javeed, Ashraf
  0 siblings, 1 reply; 51+ messages in thread
From: Javeed, Ashraf @ 2020-04-21  6:03 UTC (permalink / raw)
  To: Ni, Ray, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

About the "CompletionTimeout ", I want to retract about the AUTO option; the implementation is good and device initialization should be skipped for this option.

Regards
Ashraf

> -----Original Message-----
> From: Javeed, Ashraf <ashraf.javeed@intel.com>
> Sent: Monday, April 20, 2020 6:53 PM
> To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> <hao.a.wu@intel.com>; Javeed, Ashraf <ashraf.javeed@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
> 
> Ray,
> Sorry for late response as I got into other priorities. Let's try to finish this
> ASAP.
> Certainly the implementation of yours has reduced the code size in great
> deal by deprecating the EFI encodings for the PCIe features, and using the
> actual HW values along with the global definition of AUTO and
> NOT_APPLICABLE (as an alias to DO_NOT_TOUCH). I am concerned that lot
> of explanation in the text of the PCI Express Protocol has to be provided
> about the rules that platform FW developer has to follow w.r.t. AUTO and
> DO_NOT_TOUCH in the GetDevicePolicy(); that needs to be published in the
> PI Specification. I shall take your implementation and add the other 3 PCIe
> features that I had implemented (ExtendedTag, Aspm,
> CommonClockConfiguration) into this scheme, and also provide how these
> global options rules can be defined for the other non-implemented PCIe
> features.
> However, I have other suggestions/corrections for the present 7 PCIe
> features implementation, which I want to discuss by highlighting the
> platform policy of AUTO and DO_NOT_DISTURB.
> 
> (1) MaxPayloadSize:- This feature requires aligning all the PCI devices in the
> hierarchy to have a common value. (The device policy by platform shall be
> used to align with all the devices in hierarchy based on their capability, thus
> value less than capability shall result in all devices in hierarchy supporting
> that value in capability to be programmed).
> 	(a) AUTO: The DeviceCapability.MaxPayloadSize value is considered
> while scan all the nodes in the hierarchy
> 	(b) DO_NOT_TOUCH: Should be considered as invalid value to skip
> for this feature. Two options in this scenario...
> 		(i) The PciBusDxe shall use this option to force the HW
> default value of 128B
> 		(ii) Behave same as AUTO.
> 	I vote for option (i) above.
> 
> (2) MaxReadReqSize:- Does not need all the devices in hierarchy to be align
> to common value. However, the spec imposes that for an isochronous
> configured device its memory read request should be equal to
> MayPayloadSize; thus I accept your implementation since determining
> whether that device in Isochronous mode is beyond the scope of PciBusDxe
> 	(a) AUTO: MaxReadReqSize = MaxPayloadSize; shall cover the device
> configured in Isochronous case.
> 	(b) DO_NOT_TOUCH: skip programming the DeviceControl register
> of the device
> 
> (3) RelaxOrdering:- Specific to device to enable or disable; does not require
> any coherency with all the devices in the hierarchy
> 	(a) AUTO: device initialization is skipped
> 	(b) DO_NOT_TOUCH: device initialization is skipped
> 
> (4) NoSnoop:- Specific to device to enable or disable; does not require any
> coherency with all the devices in the hierarchy
> 	(a) AUTO: device initialization is skipped
> 	(b) DO_NOT_TOUCH: device initialization is skipped
> 
> (5) CompletionTimeout:-  The range and detection mechanism disable can
> be set specifically for any device; does not require to be aligned with all
> devices in the hierarchy
> 	(a) AUTO: your implementation ignores it (same as do not touch); I
> propose that platform can provide this option to set the
> DeviceControl2.CompletionTimeoutValue as per its high range value of
> DeviceCapability2.CompletionTimeoutRangesSupported, ignoring the
> CompletionTimeoutDisableSupported. For example; if the DeviceCapability2
> supports Ranges A, B, C and D; than its
> DeviceControl2.CompletionTimeoutValue can be programmed to 1110b
> (17s to 64s) for higher subrange.
> 	(b) DO_NOT_TOUCH: device initialization is skipped
> 	Your implementation about the device policy from platform appears
> OK to me.
> 
> (6) Ltr: As per PCIe specification, the LTR capability is provided for all the PCI
> devices, disabled by default, and if LTR needs to be enabled for Endpoint
> device than all the in-between component from Root Port to Endpoint
> needs to be enabled, and it is not required that all Endpoints have to be LTR
> enabled.
> 	(a) AUTO: as per your implementation, this option is ignored as
> invalid, and overwritten with its child device and if no valid for child device
> than device initialization is skipped
> 	(b) DO_NOT_TOUCH: as per your implementation, this option is
> ignored as invalid. and overwritten with its child device and if no valid for
> child device than device initialization is skipped
> 	Why does your implementation consider changing only the parent
> N as per its child N+1, and not vice versa? If platform only updates the Root
> port (RP) and not the Endpoint device than this implementation only
> programs the RP, right?
> 	In real scenario, the platform FW does not provide the policy for
> PCIe Endpoint devices mounted on the PCIe slots since those policies are
> statically defined to the fixed components of the chip. Thus, platform
> expects enabling the PCIe Root Port LTR mechanism, in hope that its valid
> PCIe Endpoint device gets enabled if all the devices are capable of LTR
> mechanism.
> 	I propose, even if platform provides one device to be LTR enable in
> the path from Root Port to Endpoint device, than PciBusDxe can enable all
> the devices in the path if all are LTR capable. This shall be also for Switch
> with multiple downstream ports with each port connected to independent
> Endpoint devices, if platform provide LTR enable to Root Port than enable
> for each path of devices if the downstream port's Endpoint device is LTR
> capable. If any one downstream port's Endpoint device is not capable than
> it need not set for that device.
> 
> (7) AtomicOp: As per PCIe specification, the DeviceControl2 register
> provides the AtomicOp Requester Enable bit (6) and blocking of AtomicOp
> request bit (7) for the Port device.
> 	The AtomicOp requester capability determination is out of scope,
> hence it can be just relied on platform policy request. However, the blocking
> AtomicOp request on the port device depends on the Device Routing
> capability bit defined in the DeviceCapability2 register.
> 	(a) AUTO: device initialization is skipped
> 	(b) DO_NOT_TOUCH: device initialization is skipped
> 	I think the change required in this implementation is the check for
> the Routing Capability to enable the blocking of AtomicOp request for the
> port device; do you agree?
> 
> Thanks
> Ashraf
> 
> > -----Original Message-----
> > From: Ni, Ray <ray.ni@intel.com>
> > Sent: Tuesday, March 17, 2020 9:07 PM
> > To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > <hao.a.wu@intel.com>
> > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
> >
> > Ashraf,
> > Thank you for the prompt response!
> >
> > My response in below.
> > (I removed some earlier conversations, but the context is still kept.)
> >
> > > > I take it as an agree of using the global AUTO. Thanks for that.
> > > Please note that there is another request of "Do not touch", and I
> > > am still contemplating whether both AUTO and DO_NOT_TOUCH
> options
> > could
> > > be applicable to all the PCIe features or not. It could be possible
> > > to take
> > AUTO for some of them and DO_NOT_TOUCH for others. Need to
> consider
> > each PCIe feature separately for both these options.
> >
> >
> > I think we are basically aligned on this.
> > I agree that each PCIe feature should have clear statement about how
> > to interpret AUTO and DO_NOT_TOUCH.
> > DO_NOT_TOUCH in my code change is NOT_APPLICABLE.
> > If you check some of the features I already implemented, the comments
> > say clearly what AUTO and NOT_APPLICABLE mean for that specific
> feature.
> > Looking forward to your comments on how to interpret AUTO and
> > NOT_APPLICABLE for each PCIe feature.
> >
> > > > Supposing a root bridge contains 1 RCiEP and two root ports, the
> > > > implementation ensures there will be 3 separate contexts for each.
> > > > As you can see, every time the code starts enumeration from a
> > > > RCiEP or a root port, a new Context[] is setup. Context[i] is
> > > > associated with the
> > feature _i_.
> > > >
> > > I realize now, that there are 3 nested for-loops in the
> > > EnumerateRootBridgePcieFeatures(), the first one enables the
> > > processing of first level nodes of the Root Bridge instance, and in
> > > this way
> > the context[i] used for each node will be valid as it covers each
> > node's hierarchy.
> >
> > I think we are aligned on this.
> >
> > > >
> > > > The level N and N+1 is needed for AtomicOp or Ltr feature (which I
> > > > need to go back to check the code).
> > > > I want to avoid the individual feature scan/program routine checks
> > > > device's parent/children.
> > > > I understand that in PCIE spec, a switch consists of an upstream
> > > > port and several downstream ports.
> > > > It means a switch populates a bridge which connects to the
> > > > upstream and several bridges under the upstream bridge which
> > > > connect to the downstream.
> > > > But from software perspective, I don't think we should care about
> that.
> > > > Maybe I am wrong. Can you please give a real example that treating
> > > > in my way would cause some issues?
> > > >
> > > Let just say we have PCIe switch connected to Root Port on a host,
> > > and it has 2 downstream ports, each connected to one Endpoint device
> each.
> > > Platform has selected to enable LTR for second downstream port's
> > > endpoint device, not both. As per your code logic of LTR, where you
> > > use the N and N+1 to compare between the parent and child, will not
> > > be
> > applicable if you use the same condition to check downstream port
> > (N+1), and its parent upstream port, because N would be the Endpoint
> > device of first downstream port of the PCIe switch and not its upstream
> port.
> > > Root Port ->					1|0|0
> > > Switch upstream port ->				2|0|0 (M-1)
> > > Switch downstream ports ->	3|0|0,(M)		5|0|0 (N
> (=M+2))
> > > Endpoint devices ->		4|0|0 (M+1)		6|0|0 (N+1
> (=M+3))
> > > The level+1 logic when the EnumeratePcieDevices() is called
> > > recursively, will result in one value greater than the Endpoint
> > > device for
> > the second downstream port.
> >
> > The level value in my code will be:
> > Root Port ->					1|0|0 (level 0)
> > Switch upstream port ->				2|0|0 (level 1)
> > Switch downstream ports ->	3|0|0,(level 2)		5|0|0,(level 2)
> > Endpoint devices ->		4|0|0,(level 3)		6|0|0,(level 3)
> >
> > Level of device 5|0|0 is still 2, not 4.
> >
> > I also did the unit test to ensure the LTR feature logic is good.
> >
> > For below device hierarchy with LTR enabled in 5/0/0 and 11/0/0,
> > disabled in 9/0/0 The LTR setting for upstream bridges should be as
> following:
> >                     0/4/0[LTR:1]
> >   2/0/0[1]  |       2/1/0[1]         | 2/2/0[0]
> >   3/0/0[1]  |       7/0/0[1]
> >   4/0/0[1]  |       8/0/0[1]
> >   5/0/0[1]  | 9/0/0[0]   9/1/0[1]
> >                          10/0/0[1]
> >                          11/0/0[1]
> >
> > The unit test code is in commit "Test case for LTR".
> >
> > >
> > > > >
> > > > > I liked the Pre & Post order flag that is used to processing
> > > > > parent-to-child
> > > > vs. child-to-parent nodes.
> > > >
> > > > Actually I didn't have this flag in the first version of my code
> > > > change. But later I found it's needed for some features like LTR
> > > > which needs to be programmed from rootbridge to endpoint
> according
> > to spec.
> > > >
> > > >
> > > > > You are calling the first
> > > > > and last features as fakes, when you actually parse all the
> > > > > nodes for the GetDevicePolicy() and NotifyDeviceState(); to me
> > > > > it is actually an un-named phase where all the nodes are queried
> > > > > or informed to the
> > > > platform; that seems fine to save the NULL on the mPcieFeatures[]
> > table.
> > > >
> > > > Yes I put GetDevicePolicy() and NotifyDeviceState() in the feature
> > > > array in my first version of code. And later I called the two
> > > > separately for better code readability. But it was my fault that I
> > > > didn't update the commit message. It caused confusion to you.
> > > >
> > > > >
> > > > > Thanks
> > > > > Ashraf
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Ni, Ray <ray.ni@intel.com>
> > > > > > Sent: Thursday, March 5, 2020 7:43 PM
> > > > > > To: devel@edk2.groups.io; Ni, Ray <ray.ni@intel.com>; Javeed,
> > > > > > Ashraf <ashraf.javeed@intel.com>
> > > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > > <hao.a.wu@intel.com>
> > > > > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2
> > PATCH
> > > > > > 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > > > >
> > > > > > Ashraf,
> > > > > > I think it might be better to describe my review comments with
> > > > > > code implementation.
> > > > > > Can you please check this branch where I did some modification
> > > > > > based on your code?
> > > > > > https://github.com/niruiyu/edk2/tree/pci/pcie2
> > > > > >
> > > > > > Let's firstly align on the feature initialization framework
> > > > implementation.
> > > > > > To be specific, this commit:
> > > > > > MdeModulePkg/PciBus: Add the framework to init PCIE features
> > > > > >
> > > >
> >
> https://github.com/niruiyu/edk2/commit/9fb9a3dcef06de98a76825e2fc0
> > > > > > 7167446ee6fd9
> > > > > >
> > > > > > Thanks,
> > > > > > Ray
> > > > > >
> > > > > > > -----Original Message-----
> > > > > > > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf
> > Of
> > > > Ni,
> > > > > > Ray
> > > > > > > Sent: Thursday, December 19, 2019 1:49 PM
> > > > > > > To: Javeed, Ashraf <ashraf.javeed@intel.com>;
> > > > > > > devel@edk2.groups.io
> > > > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > > > <hao.a.wu@intel.com>
> > > > > > > Subject: Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2
> > > > > > > PATCH 05/12]
> > > > > > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > > > > >
> > > > > > > After I reviewed the patch of enabling MaxPayloadSize,
> > > > > > > MaxReadReqSize and more PCIE features, I can now understand
> > > > > > > the phases more than earlier.
> > > > > > >
> > > > > > > Your patch proposed five phases:
> > > > > > >   //
> > > > > > >   // 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
> > > > > > >
> > > > > > >
> > > > > > > I have several comments to the five phases.
> > > > > > > 1. Scan phase is not do the scanning but creates a list to
> > > > > > > hold all root ports under the root bridge.
> > > > > > > 2. Root ports collection is not required by all of the
> > > > > > > features, only by MPS and MRRS.
> > > > > > > But the collection always happens even when platform doesn't
> > > > > > > require PciBus to initialize MPS or MRRS.
> > > > > > > 3. GetDevicePolicy phase is not just call the
> > > > > > > GetDevicePolicy for each device. It also reads the PCIE
> > > > > > > configuration space to get the device's feature related
> > > > > > > capabilities, for some of the
> > features.
> > > > > > >
> > > > > > > With that, I propose to define 4 phases:
> > > > > > > 1. Initialize phase
> > > > > > > This phase is similar to your Scan phase.
> > > > > > > For some features, this phase does nothing.
> > > > > > > For MPS and MRRS, this phase creates a list holding all root
> ports.
> > > > > > >
> > > > > > > 2. Scan phase
> > > > > > > This phase is similar to your GetDevicePolicy phase.
> > > > > > > For some features, this phase needs nothing do to.
> > > > > > > For MPS and MRRS, this phase scan all devices and get the
> > > > > > > aligned value of MPS or MRRS.
> > > > > > >
> > > > > > > 3. Program phase or Configuration phase This phase is
> > > > > > > similar to your Configuration phase.
> > > > > > > The Setup phase can be merged to this phase.
> > > > > > >
> > > > > > > 4. Finalize phase.
> > > > > > > This phase is similar to your ConfigurationComplete phase.
> > > > > > > This phase frees the resources occupied/allocated in
> > > > > > > Initialize
> > phase.
> > > > > > > For some of the features, this phase may do nothing.
> > > > > > >
> > > > > > > Each feature needs to provide function pointers for each
> > > > > > > phase and NULL means the feature doesn't need to do anything
> > > > > > > in the specific phase.
> > > > > > > With that, we can define a structure:
> > > > > > > Typedef struct {
> > > > > > >   BOOLEAN                          Enable;
> > > > > > >   PCIE_FEATURE_INITILAIZE Initialize;
> > > > > > >   PCIE_FEATURE_SCAN  Scan;
> > > > > > >   PCIE_FEATURE_PROGRAM Program;
> > > > > > >   PCIE_FEATURE_FINALIZE Finalize; } PCIE_FEATURE_ENTRY;
> > > > > > >
> > > > > > > With that, we can define a module level global variable:
> > > > > > > PCIE_FEATURE_ENTRY mPcieFeatures[] = {
> > > > > > >   { TRUE, MaxPayloadInitialize, MaxPayloadScan,
> > > > > > > MaxPayloadProgram, MaxPayloadFinalize},
> > > > > > >   { TRUE, MaxReadRequestInitialize, MaxReadRequestScan,
> > > > > > > MaxReadRequestProgram, MaxReadRequestFinalize},
> > > > > > >   { TRUE, NULL, NULL, RelaxOrderProgram, NULL},
> > > > > > >   { TRUE, NULL, CompletionTimeoutScan,
> > > > > > > CompletionTimeoutProgram,
> > > > > > NULL },
> > > > > > >   ...
> > > > > > > };
> > > > > > >
> > > > > > > PCIE_FEATURE_ENTRY.Enable can be set to FALSE according to
> > > > > > > the platform policy.
> > > > > > >
> > > > > > > The enable of PCIE features can be written as a feature
> > > > > > > agnostic for-
> > > > loop.
> > > > > > > This can make the new feature enabling code easy to add and
> > review.
> > > > > > >
> > > > > > >
> > > > > > > > -----Original Message-----
> > > > > > > > From: Javeed, Ashraf <ashraf.javeed@intel.com>
> > > > > > > > Sent: Wednesday, December 18, 2019 3:14 PM
> > > > > > > > To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> > > > > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > > > > <hao.a.wu@intel.com>
> > > > > > > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2
> > > > PATCH
> > > > > > > > 05/12]
> > > > > > > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > > > > > >
> > > > > > > > Thanks for the review, Ray!
> > > > > > > > My response in line
> > > > > > > >
> > > > > > > > > -----Original Message-----
> > > > > > > > > From: Ni, Ray <ray.ni@intel.com>
> > > > > > > > > Sent: Tuesday, December 17, 2019 5:26 PM
> > > > > > > > > To: Javeed, Ashraf <ashraf.javeed@intel.com>;
> > > > > > > > > devel@edk2.groups.io
> > > > > > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > > > > > <hao.a.wu@intel.com>
> > > > > > > > > Subject: RE: [edk2-devel]
> > > > > > > > > [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > > > > > > > 05/12]
> > > > > > > > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > > > > > > >
> > > > > > > > > Please check comments below.
> > > > > > > > > I may have more comments regarding to the four phases
> > > > > > > > > after I finish
> > > > > > > > review of
> > > > > > > > > further patches.
> > > > > > > > >
> > > > > > > > > Besides the comments below, I have a general comments to
> > > > > > > > > the debug
> > > > > > > > > message: can you please review the existing debug
> > > > > > > > > message in the PciBus
> > > > > > > > driver
> > > > > > > > > and make sure your newly added debug message aligns to
> > > > > > > > > existing
> > > > > > style.
> > > > > > > > And try
> > > > > > > > > to use less lines of debug messages with still enough
> > > > > > > > > debug
> > > > > > information.
> > > > > > > > Ok, will look into that.
> > > > > > > >
> > > > > > > > >
> > > > > > > > > > > +PRIMARY_ROOT_PORT_NODE
> > > > > > *mPrimaryRootPortList;
> > > > > > > > > > > +
> > > > > > > > > > > +/**
> > > > > > > > > > > +  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;
> > > > > > > > >
> > > > > > > > > 1. Please follow existing linked list usage style. The
> > > > > > > > > first node in the list is an empty header node.
> > > > > > > > >
> > > > > > > > > LIST_ENTRY   mPrimaryRootPortList;
> > > > > > > > > LIST_ENTRY   mPciFeaturesConfigurationCompletionList;
> > > > > > > > >
> > > > > > > > Ok, will make the change when I incorporate the ECR 0.75
> > > > > > > > or greater
> > > > > > version.
> > > > > > > >
> > > > > > > > > > > +BOOLEAN
> > > > > > > > > > > +CheckPciFeatureConfigurationRecordExist (
> > > > > > > > > > > +  IN  PCI_IO_DEVICE                             *RootBridge,
> > > > > > > > > > > +  OUT
> PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > > > > > > > > +**PciFeatureConfigRecord
> > > > > > > > > > > +  )
> > > > > > > > >
> > > > > > > > > 2. Is this function to check whether the PCIE features
> > > > > > > > > under a root bridge is already initialized?
> > > > > > > > > Can you use the existing variable gFullEnumeration?
> > > > > > > > > The variable is set to TRUE when the enumeration is done
> > > > > > > > > to a host bridge
> > > > > > > > in the
> > > > > > > > > first time.
> > > > > > > > > By using gFullEnumeration, the entire function is not needed.
> > > > > > > > >
> > > > > > > > Ok, will look into this.
> > > > > > > >
> > > > > > > > > > > +EFI_STATUS
> > > > AddRootBridgeInPciFeaturesConfigCompletionList (
> > > > > > > > > > > +  IN PCI_IO_DEVICE          *RootBridge,
> > > > > > > > > > > +  IN BOOLEAN                ReEnumerationRequired
> > > > > > > > > > > +  )
> > > > > > > > >
> > > > > > > > > 3. Same question as #2. I think by using
> > > > > > > > > gFullEnumeration, this function is
> > > > > > > > not
> > > > > > > > > needed.
> > > > > > > > >
> > > > > > > > OK
> > > > > > > >
> > > > > > > > >
> > > > > > > > > > > +BOOLEAN
> > > > > > > > > > > +IsPciRootPortEmpty (
> > > > > > > > > > > +  IN  PCI_IO_DEVICE                           *PciDevice
> > > > > > > > > > > +  )
> > > > > > > > >
> > > > > > > > > 4. Please use IsListEmpty() directly from callers and
> > > > > > > > > remove this
> > > > > > function.
> > > > > > > > >
> > > > > > > > Will consider this.
> > > > > > > >
> > > > > > > > > > > +**/
> > > > > > > > > > > +EFI_STATUS
> > > > > > > > > > > +EnumerateOtherPciFeatures (
> > > > > > > > >
> > > > > > > > > 5. Can it be "EnumeratePcieFeatures"?
> > > > > > > > >
> > > > > > > > Yes, with the change to ECR 0.75, this routine name shall
> > > > > > > > be
> > > > changed.
> > > > > > > >
> > > > > > > > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > > > > > > > > +  )
> > > > > > > > > > > +{
> > > > > > > > > > > +  EFI_STATUS            Status;
> > > > > > > > > > > +  UINTN                 OtherPciFeatureConfigPhase;
> > > > > > > > > > > +
> > > > > > > > > > > +  //
> > > > > > > > > > > +  // check on PCI features configuration is
> > > > > > > > > > > + complete and re-enumeration is required  //  if
> > > > > > > > > > > + (!CheckPciFeaturesConfigurationRequired
> > > > > > > > > > > + (RootBridge)) {
> > > > > > > > > > > +    return EFI_ALREADY_STARTED;  }
> > > > > > > > > > > +
> > > > > > > > >  > > +  CHAR16                *Str;
> > > > > > > > > > > +  Str = ConvertDevicePathToText (
> > > > > > > > > > > +          DevicePathFromHandle (RootBridge->Handle),
> > > > > > > > > > > +          FALSE,
> > > > > > > > > > > +          FALSE
> > > > > > > > > > > +        );
> > > > > > > > > > > +  DEBUG ((DEBUG_INFO, "Enumerating PCI features for
> > > > > > > > > > > + Root Bridge %s\n", Str != NULL ? Str : L""));
> > > > > > > > >
> > > > > > > > > 6. Please use DEBUG_CODE macro to include
> > > > > > > > > ConvertDevicePathToText()
> > > > > > > > and
> > > > > > > > > DEBUG().
> > > > > > > > > Please remember to call FreePool().
> > > > > > > > >
> > > > > > > > Ok, will can under DEBUG_CODE, and free pool is called in
> > > > > > > > the end
> > > > > > > >
> > > > > > > > > > > +
> > > > > > > > > > > +  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);
> > > > > > > > >
> > > > > > > > > 7. How about "RecordPciRootPorts (RootBridge)"? The
> > "Bridges"
> > > > > > > > > suffix is a
> > > > > > > > bit
> > > > > > > > > confusing.
> > > > > > > > >
> > > > > > > > Fine, will change.
> > > > > > > >
> > > > > > > > > > > +      case  PciFeatureGetDevicePolicy:
> > > > > > > > > > > +      case  PciFeatureSetupPhase:
> > > > > > > > >
> > > > > > > > > 8. In SetupPciFeatures(), why do you need to call
> DeviceExist()?
> > > > > > > > > Did you see any case that a device is detected in the
> > > > > > > > > beginning of PciBus
> > > > > > > > scan
> > > > > > > > > but is hidden when calling SetupPciFeatures()?
> > > > > > > > >
> > > > > > > > Yes, that is the case; device detected during the
> > > > > > > > beginning of PciBus scan appears to be hidden by the
> > > > > > > > platform drivers, since numerous legacy callbacks are
> > > > > > > > initiated at different phase of PCI enumeration to the PCI
> > > > > > > > Host Bridge, and
> > PciPlatform drivers.
> > > > > > > > This can be avoided if the PciBus driver is enhanced to
> > > > > > > > check for PCI device existence before the publication of
> > > > > > > > the PCI IO Protocol, and removal of the PCI_IO_DEVICE
> > > > > > > > instance from the
> > > > linked list.
> > > > > > > >
> > > > > > > > > 9. In GetPciFeaturesConfigurationTable() when checking
> > > > > > > > > whether a PCI
> > > > > > > > device
> > > > > > > > > belongs to a root port, we can use below simpler logic:
> > > > > > > > >   SizeOfPciDevicePath = GetDevicePathSize (PciDevicePath);
> > > > > > > > >   SizeOfRootPortDevicePath = GetDevicePathSize
> > (RootPortPath);
> > > > > > > > >   if ((SizeOfRootPortDevicePath < SizeOfPciDevicePath) &&
> > > > > > > > >       CompareMem (PciDevicePath, RootPortPath,
> > > > > > > > SizeOfRootPortDevicePath -
> > > > > > > > > END_DEVICE_PATH_LENGTH) == 0)) {
> > > > > > > > >     // PCI device belongs to the root port.
> > > > > > > > >   }
> > > > > > > > >
> > > > > > > > Ok.
> > > > > > > >
> > > > > > > > > > > +        Status = ProgramPciFeatures (RootBridge);
> > > > > > > > > 10. ProgramPcieFeatures()?
> > > > > > > > >
> > > > > > > > OK
> > > > > > > >
> > > > > > > > > > > +
> > > > > > > > > > > +  if (Str != NULL) {
> > > > > > > > > > > +    FreePool (Str);  }
> > > > > > > > >
> > > > > > > > > 11. OK the Str is freed here because Str is needed for
> > > > > > > > > other debug
> > > > > > > > messages
> > > > > > > > > inside the function.
> > > > > > > > >
> > > > > > > > Yes
> > > > > > > >
> > > > > > > > > > > +  //
> > > > > > > > > > > +  // mark this root bridge as PCI features
> > > > > > > > > > > +configuration complete, and no new
> > > > > > > > > > > +  // enumeration is required
> > > > > > > > > > > +  //
> > > > > > > > > > > +  AddRootBridgeInPciFeaturesConfigCompletionList
> > > > > > > > > > > +(RootBridge, FALSE);
> > > > > > > > >
> > > > > > > > > 12. Not needed.
> > > > > > > > >
> > > > > > > > ok, after incorporating the logic of gFullEnumeration it
> > > > > > > > won't be required
> > > > > > > >
> > > > > > > > > > > +_PRIMARY_ROOT_PORT_NODE {
> > > > > > > > >
> > > > > > > > > > > +  //
> > > > > > > > > > > +  // Signature header
> > > > > > > > > > > +  //
> > > > > > > > > > > +  UINT32                                    Signature;
> > > > > > > > > > > +  //
> > > > > > > > > > > +  // linked list pointers to next node
> > > > > > > > > > > +  //
> > > > > > > > > > > +  LIST_ENTRY                                NeighborRootPort;
> > > > > > > > > > > +  //
> > > > > > > > > > > +  // pointer to PCI_IO_DEVICE of the primary PCI
> > > > > > > > > > > +Controller device
> > > > > > > > > > > +  //
> > > > > > > > > > > +  EFI_DEVICE_PATH_PROTOCOL
> > > > *RootPortDevicePath;
> > > > > > > > > > > +  //
> > > > > > > > > > > +  // pointer to the corresponding PCI feature
> > > > > > > > > > > +configuration Table node
> > > > > > > > > > > +  // all the child PCI devices of the controller
> > > > > > > > > > > +are aligned based on this table
> > > > > > > > > > > +  //
> > > > > > > > > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > > > > > > *OtherPciFeaturesConfigurationTable;
> > > > > > > > > > > +};
> > > > > > > > >
> > > > > > > > > 13. Can you add the
> > > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > field
> > > > > > > > to
> > > > > > > > > PCI_IO_DEVICE structure?
> > > > > > > > > So this structure PRIMARY_ROOT_PORT_NODE is not
> needed.
> > > > > > > > >
> > > > > > > > I think it is better to maintain separately as this
> > > > > > > > configuration table is confined to a group of PCI devices
> > > > > > > > and for the RCiEP it is not applicable hence not required.
> > > > > > > > Moreover, I am maintaining a variable for each PCIe
> > > > > > > > feature in the PCI_IO_DEVICE; perhaps I can
> > > > > > consider having just pointer of it....
> > > > > > > >
> > > > > > > > > > > +struct
> > _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
> > > > > > > > > 14. This structure is not needed if using gFullEnumeration.
> > > > > > > > Yes.
> > > > > > >
> > > > > > > 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
  2020-04-21  6:03                       ` Javeed, Ashraf
@ 2020-04-21  6:22                         ` Javeed, Ashraf
  2020-05-08  8:26                           ` Ni, Ray
  0 siblings, 1 reply; 51+ messages in thread
From: Javeed, Ashraf @ 2020-04-21  6:22 UTC (permalink / raw)
  To: Ni, Ray, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

About the "AtomicOp", I want to retract about the check for the Routing Capability to set the platform policy about the blocking the AtomicOp requests. The implementation seems good.

Thanks
Ashraf

> -----Original Message-----
> From: Javeed, Ashraf
> Sent: Tuesday, April 21, 2020 11:33 AM
> To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> <hao.a.wu@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
> 
> About the "CompletionTimeout ", I want to retract about the AUTO option;
> the implementation is good and device initialization should be skipped for
> this option.
> 
> Regards
> Ashraf
> 
> > -----Original Message-----
> > From: Javeed, Ashraf <ashraf.javeed@intel.com>
> > Sent: Monday, April 20, 2020 6:53 PM
> > To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > <hao.a.wu@intel.com>; Javeed, Ashraf <ashraf.javeed@intel.com>
> > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
> >
> > Ray,
> > Sorry for late response as I got into other priorities. Let's try to
> > finish this ASAP.
> > Certainly the implementation of yours has reduced the code size in
> > great deal by deprecating the EFI encodings for the PCIe features, and
> > using the actual HW values along with the global definition of AUTO
> > and NOT_APPLICABLE (as an alias to DO_NOT_TOUCH). I am concerned
> that
> > lot of explanation in the text of the PCI Express Protocol has to be
> > provided about the rules that platform FW developer has to follow
> > w.r.t. AUTO and DO_NOT_TOUCH in the GetDevicePolicy(); that needs to
> > be published in the PI Specification. I shall take your implementation
> > and add the other 3 PCIe features that I had implemented (ExtendedTag,
> > Aspm,
> > CommonClockConfiguration) into this scheme, and also provide how
> these
> > global options rules can be defined for the other non-implemented PCIe
> > features.
> > However, I have other suggestions/corrections for the present 7 PCIe
> > features implementation, which I want to discuss by highlighting the
> > platform policy of AUTO and DO_NOT_DISTURB.
> >
> > (1) MaxPayloadSize:- This feature requires aligning all the PCI
> > devices in the hierarchy to have a common value. (The device policy by
> > platform shall be used to align with all the devices in hierarchy
> > based on their capability, thus value less than capability shall
> > result in all devices in hierarchy supporting that value in capability to be
> programmed).
> > 	(a) AUTO: The DeviceCapability.MaxPayloadSize value is considered
> > while scan all the nodes in the hierarchy
> > 	(b) DO_NOT_TOUCH: Should be considered as invalid value to skip
> for
> > this feature. Two options in this scenario...
> > 		(i) The PciBusDxe shall use this option to force the HW
> default
> > value of 128B
> > 		(ii) Behave same as AUTO.
> > 	I vote for option (i) above.
> >
> > (2) MaxReadReqSize:- Does not need all the devices in hierarchy to be
> > align to common value. However, the spec imposes that for an
> > isochronous configured device its memory read request should be equal
> > to MayPayloadSize; thus I accept your implementation since determining
> > whether that device in Isochronous mode is beyond the scope of
> PciBusDxe
> > 	(a) AUTO: MaxReadReqSize = MaxPayloadSize; shall cover the device
> > configured in Isochronous case.
> > 	(b) DO_NOT_TOUCH: skip programming the DeviceControl register
> of the
> > device
> >
> > (3) RelaxOrdering:- Specific to device to enable or disable; does not
> > require any coherency with all the devices in the hierarchy
> > 	(a) AUTO: device initialization is skipped
> > 	(b) DO_NOT_TOUCH: device initialization is skipped
> >
> > (4) NoSnoop:- Specific to device to enable or disable; does not
> > require any coherency with all the devices in the hierarchy
> > 	(a) AUTO: device initialization is skipped
> > 	(b) DO_NOT_TOUCH: device initialization is skipped
> >
> > (5) CompletionTimeout:-  The range and detection mechanism disable can
> > be set specifically for any device; does not require to be aligned
> > with all devices in the hierarchy
> > 	(a) AUTO: your implementation ignores it (same as do not touch); I
> > propose that platform can provide this option to set the
> > DeviceControl2.CompletionTimeoutValue as per its high range value of
> > DeviceCapability2.CompletionTimeoutRangesSupported, ignoring the
> > CompletionTimeoutDisableSupported. For example; if the
> > DeviceCapability2 supports Ranges A, B, C and D; than its
> > DeviceControl2.CompletionTimeoutValue can be programmed to 1110b
> (17s
> > to 64s) for higher subrange.
> > 	(b) DO_NOT_TOUCH: device initialization is skipped
> > 	Your implementation about the device policy from platform appears
> OK
> > to me.
> >
> > (6) Ltr: As per PCIe specification, the LTR capability is provided for
> > all the PCI devices, disabled by default, and if LTR needs to be
> > enabled for Endpoint device than all the in-between component from
> > Root Port to Endpoint needs to be enabled, and it is not required that
> > all Endpoints have to be LTR enabled.
> > 	(a) AUTO: as per your implementation, this option is ignored as
> > invalid, and overwritten with its child device and if no valid for
> > child device than device initialization is skipped
> > 	(b) DO_NOT_TOUCH: as per your implementation, this option is
> ignored
> > as invalid. and overwritten with its child device and if no valid for
> > child device than device initialization is skipped
> > 	Why does your implementation consider changing only the parent
> N as
> > per its child N+1, and not vice versa? If platform only updates the
> > Root port (RP) and not the Endpoint device than this implementation
> > only programs the RP, right?
> > 	In real scenario, the platform FW does not provide the policy for
> > PCIe Endpoint devices mounted on the PCIe slots since those policies
> > are statically defined to the fixed components of the chip. Thus,
> > platform expects enabling the PCIe Root Port LTR mechanism, in hope
> > that its valid PCIe Endpoint device gets enabled if all the devices
> > are capable of LTR mechanism.
> > 	I propose, even if platform provides one device to be LTR enable in
> > the path from Root Port to Endpoint device, than PciBusDxe can enable
> > all the devices in the path if all are LTR capable. This shall be also
> > for Switch with multiple downstream ports with each port connected to
> > independent Endpoint devices, if platform provide LTR enable to Root
> > Port than enable for each path of devices if the downstream port's
> > Endpoint device is LTR capable. If any one downstream port's Endpoint
> > device is not capable than it need not set for that device.
> >
> > (7) AtomicOp: As per PCIe specification, the DeviceControl2 register
> > provides the AtomicOp Requester Enable bit (6) and blocking of
> > AtomicOp request bit (7) for the Port device.
> > 	The AtomicOp requester capability determination is out of scope,
> > hence it can be just relied on platform policy request. However, the
> > blocking AtomicOp request on the port device depends on the Device
> > Routing capability bit defined in the DeviceCapability2 register.
> > 	(a) AUTO: device initialization is skipped
> > 	(b) DO_NOT_TOUCH: device initialization is skipped
> > 	I think the change required in this implementation is the check for
> > the Routing Capability to enable the blocking of AtomicOp request for
> > the port device; do you agree?
> >
> > Thanks
> > Ashraf
> >
> > > -----Original Message-----
> > > From: Ni, Ray <ray.ni@intel.com>
> > > Sent: Tuesday, March 17, 2020 9:07 PM
> > > To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > <hao.a.wu@intel.com>
> > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > > 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
> > >
> > > Ashraf,
> > > Thank you for the prompt response!
> > >
> > > My response in below.
> > > (I removed some earlier conversations, but the context is still
> > > kept.)
> > >
> > > > > I take it as an agree of using the global AUTO. Thanks for that.
> > > > Please note that there is another request of "Do not touch", and I
> > > > am still contemplating whether both AUTO and DO_NOT_TOUCH
> > options
> > > could
> > > > be applicable to all the PCIe features or not. It could be
> > > > possible to take
> > > AUTO for some of them and DO_NOT_TOUCH for others. Need to
> > consider
> > > each PCIe feature separately for both these options.
> > >
> > >
> > > I think we are basically aligned on this.
> > > I agree that each PCIe feature should have clear statement about how
> > > to interpret AUTO and DO_NOT_TOUCH.
> > > DO_NOT_TOUCH in my code change is NOT_APPLICABLE.
> > > If you check some of the features I already implemented, the
> > > comments say clearly what AUTO and NOT_APPLICABLE mean for that
> > > specific
> > feature.
> > > Looking forward to your comments on how to interpret AUTO and
> > > NOT_APPLICABLE for each PCIe feature.
> > >
> > > > > Supposing a root bridge contains 1 RCiEP and two root ports, the
> > > > > implementation ensures there will be 3 separate contexts for each.
> > > > > As you can see, every time the code starts enumeration from a
> > > > > RCiEP or a root port, a new Context[] is setup. Context[i] is
> > > > > associated with the
> > > feature _i_.
> > > > >
> > > > I realize now, that there are 3 nested for-loops in the
> > > > EnumerateRootBridgePcieFeatures(), the first one enables the
> > > > processing of first level nodes of the Root Bridge instance, and
> > > > in this way
> > > the context[i] used for each node will be valid as it covers each
> > > node's hierarchy.
> > >
> > > I think we are aligned on this.
> > >
> > > > >
> > > > > The level N and N+1 is needed for AtomicOp or Ltr feature (which
> > > > > I need to go back to check the code).
> > > > > I want to avoid the individual feature scan/program routine
> > > > > checks device's parent/children.
> > > > > I understand that in PCIE spec, a switch consists of an upstream
> > > > > port and several downstream ports.
> > > > > It means a switch populates a bridge which connects to the
> > > > > upstream and several bridges under the upstream bridge which
> > > > > connect to the downstream.
> > > > > But from software perspective, I don't think we should care
> > > > > about
> > that.
> > > > > Maybe I am wrong. Can you please give a real example that
> > > > > treating in my way would cause some issues?
> > > > >
> > > > Let just say we have PCIe switch connected to Root Port on a host,
> > > > and it has 2 downstream ports, each connected to one Endpoint
> > > > device
> > each.
> > > > Platform has selected to enable LTR for second downstream port's
> > > > endpoint device, not both. As per your code logic of LTR, where
> > > > you use the N and N+1 to compare between the parent and child,
> > > > will not be
> > > applicable if you use the same condition to check downstream port
> > > (N+1), and its parent upstream port, because N would be the Endpoint
> > > device of first downstream port of the PCIe switch and not its
> > > upstream
> > port.
> > > > Root Port ->					1|0|0
> > > > Switch upstream port ->				2|0|0 (M-1)
> > > > Switch downstream ports ->	3|0|0,(M)		5|0|0 (N
> > (=M+2))
> > > > Endpoint devices ->		4|0|0 (M+1)		6|0|0 (N+1
> > (=M+3))
> > > > The level+1 logic when the EnumeratePcieDevices() is called
> > > > recursively, will result in one value greater than the Endpoint
> > > > device for
> > > the second downstream port.
> > >
> > > The level value in my code will be:
> > > Root Port ->					1|0|0 (level 0)
> > > Switch upstream port ->				2|0|0 (level 1)
> > > Switch downstream ports ->	3|0|0,(level 2)		5|0|0,(level
> 2)
> > > Endpoint devices ->		4|0|0,(level 3)		6|0|0,(level
> 3)
> > >
> > > Level of device 5|0|0 is still 2, not 4.
> > >
> > > I also did the unit test to ensure the LTR feature logic is good.
> > >
> > > For below device hierarchy with LTR enabled in 5/0/0 and 11/0/0,
> > > disabled in 9/0/0 The LTR setting for upstream bridges should be as
> > following:
> > >                     0/4/0[LTR:1]
> > >   2/0/0[1]  |       2/1/0[1]         | 2/2/0[0]
> > >   3/0/0[1]  |       7/0/0[1]
> > >   4/0/0[1]  |       8/0/0[1]
> > >   5/0/0[1]  | 9/0/0[0]   9/1/0[1]
> > >                          10/0/0[1]
> > >                          11/0/0[1]
> > >
> > > The unit test code is in commit "Test case for LTR".
> > >
> > > >
> > > > > >
> > > > > > I liked the Pre & Post order flag that is used to processing
> > > > > > parent-to-child
> > > > > vs. child-to-parent nodes.
> > > > >
> > > > > Actually I didn't have this flag in the first version of my code
> > > > > change. But later I found it's needed for some features like LTR
> > > > > which needs to be programmed from rootbridge to endpoint
> > according
> > > to spec.
> > > > >
> > > > >
> > > > > > You are calling the first
> > > > > > and last features as fakes, when you actually parse all the
> > > > > > nodes for the GetDevicePolicy() and NotifyDeviceState(); to me
> > > > > > it is actually an un-named phase where all the nodes are
> > > > > > queried or informed to the
> > > > > platform; that seems fine to save the NULL on the
> > > > > mPcieFeatures[]
> > > table.
> > > > >
> > > > > Yes I put GetDevicePolicy() and NotifyDeviceState() in the
> > > > > feature array in my first version of code. And later I called
> > > > > the two separately for better code readability. But it was my
> > > > > fault that I didn't update the commit message. It caused confusion
> to you.
> > > > >
> > > > > >
> > > > > > Thanks
> > > > > > Ashraf
> > > > > >
> > > > > > > -----Original Message-----
> > > > > > > From: Ni, Ray <ray.ni@intel.com>
> > > > > > > Sent: Thursday, March 5, 2020 7:43 PM
> > > > > > > To: devel@edk2.groups.io; Ni, Ray <ray.ni@intel.com>;
> > > > > > > Javeed, Ashraf <ashraf.javeed@intel.com>
> > > > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > > > <hao.a.wu@intel.com>
> > > > > > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2
> > > PATCH
> > > > > > > 05/12] PciBusDxe: Setup sub-phases for PCI feature
> > > > > > > enumeration
> > > > > > >
> > > > > > > Ashraf,
> > > > > > > I think it might be better to describe my review comments
> > > > > > > with code implementation.
> > > > > > > Can you please check this branch where I did some
> > > > > > > modification based on your code?
> > > > > > > https://github.com/niruiyu/edk2/tree/pci/pcie2
> > > > > > >
> > > > > > > Let's firstly align on the feature initialization framework
> > > > > implementation.
> > > > > > > To be specific, this commit:
> > > > > > > MdeModulePkg/PciBus: Add the framework to init PCIE features
> > > > > > >
> > > > >
> > >
> >
> https://github.com/niruiyu/edk2/commit/9fb9a3dcef06de98a76825e2fc0
> > > > > > > 7167446ee6fd9
> > > > > > >
> > > > > > > Thanks,
> > > > > > > Ray
> > > > > > >
> > > > > > > > -----Original Message-----
> > > > > > > > From: devel@edk2.groups.io <devel@edk2.groups.io> On
> > > > > > > > Behalf
> > > Of
> > > > > Ni,
> > > > > > > Ray
> > > > > > > > Sent: Thursday, December 19, 2019 1:49 PM
> > > > > > > > To: Javeed, Ashraf <ashraf.javeed@intel.com>;
> > > > > > > > devel@edk2.groups.io
> > > > > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > > > > <hao.a.wu@intel.com>
> > > > > > > > Subject: Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2
> > > > > > > > PATCH 05/12]
> > > > > > > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > > > > > >
> > > > > > > > After I reviewed the patch of enabling MaxPayloadSize,
> > > > > > > > MaxReadReqSize and more PCIE features, I can now
> > > > > > > > understand the phases more than earlier.
> > > > > > > >
> > > > > > > > Your patch proposed five phases:
> > > > > > > >   //
> > > > > > > >   // 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
> > > > > > > >
> > > > > > > >
> > > > > > > > I have several comments to the five phases.
> > > > > > > > 1. Scan phase is not do the scanning but creates a list to
> > > > > > > > hold all root ports under the root bridge.
> > > > > > > > 2. Root ports collection is not required by all of the
> > > > > > > > features, only by MPS and MRRS.
> > > > > > > > But the collection always happens even when platform
> > > > > > > > doesn't require PciBus to initialize MPS or MRRS.
> > > > > > > > 3. GetDevicePolicy phase is not just call the
> > > > > > > > GetDevicePolicy for each device. It also reads the PCIE
> > > > > > > > configuration space to get the device's feature related
> > > > > > > > capabilities, for some of the
> > > features.
> > > > > > > >
> > > > > > > > With that, I propose to define 4 phases:
> > > > > > > > 1. Initialize phase
> > > > > > > > This phase is similar to your Scan phase.
> > > > > > > > For some features, this phase does nothing.
> > > > > > > > For MPS and MRRS, this phase creates a list holding all
> > > > > > > > root
> > ports.
> > > > > > > >
> > > > > > > > 2. Scan phase
> > > > > > > > This phase is similar to your GetDevicePolicy phase.
> > > > > > > > For some features, this phase needs nothing do to.
> > > > > > > > For MPS and MRRS, this phase scan all devices and get the
> > > > > > > > aligned value of MPS or MRRS.
> > > > > > > >
> > > > > > > > 3. Program phase or Configuration phase This phase is
> > > > > > > > similar to your Configuration phase.
> > > > > > > > The Setup phase can be merged to this phase.
> > > > > > > >
> > > > > > > > 4. Finalize phase.
> > > > > > > > This phase is similar to your ConfigurationComplete phase.
> > > > > > > > This phase frees the resources occupied/allocated in
> > > > > > > > Initialize
> > > phase.
> > > > > > > > For some of the features, this phase may do nothing.
> > > > > > > >
> > > > > > > > Each feature needs to provide function pointers for each
> > > > > > > > phase and NULL means the feature doesn't need to do
> > > > > > > > anything in the specific phase.
> > > > > > > > With that, we can define a structure:
> > > > > > > > Typedef struct {
> > > > > > > >   BOOLEAN                          Enable;
> > > > > > > >   PCIE_FEATURE_INITILAIZE Initialize;
> > > > > > > >   PCIE_FEATURE_SCAN  Scan;
> > > > > > > >   PCIE_FEATURE_PROGRAM Program;
> > > > > > > >   PCIE_FEATURE_FINALIZE Finalize; } PCIE_FEATURE_ENTRY;
> > > > > > > >
> > > > > > > > With that, we can define a module level global variable:
> > > > > > > > PCIE_FEATURE_ENTRY mPcieFeatures[] = {
> > > > > > > >   { TRUE, MaxPayloadInitialize, MaxPayloadScan,
> > > > > > > > MaxPayloadProgram, MaxPayloadFinalize},
> > > > > > > >   { TRUE, MaxReadRequestInitialize, MaxReadRequestScan,
> > > > > > > > MaxReadRequestProgram, MaxReadRequestFinalize},
> > > > > > > >   { TRUE, NULL, NULL, RelaxOrderProgram, NULL},
> > > > > > > >   { TRUE, NULL, CompletionTimeoutScan,
> > > > > > > > CompletionTimeoutProgram,
> > > > > > > NULL },
> > > > > > > >   ...
> > > > > > > > };
> > > > > > > >
> > > > > > > > PCIE_FEATURE_ENTRY.Enable can be set to FALSE according to
> > > > > > > > the platform policy.
> > > > > > > >
> > > > > > > > The enable of PCIE features can be written as a feature
> > > > > > > > agnostic for-
> > > > > loop.
> > > > > > > > This can make the new feature enabling code easy to add
> > > > > > > > and
> > > review.
> > > > > > > >
> > > > > > > >
> > > > > > > > > -----Original Message-----
> > > > > > > > > From: Javeed, Ashraf <ashraf.javeed@intel.com>
> > > > > > > > > Sent: Wednesday, December 18, 2019 3:14 PM
> > > > > > > > > To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> > > > > > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > > > > > <hao.a.wu@intel.com>
> > > > > > > > > Subject: RE: [edk2-devel]
> > > > > > > > > [edk2-staging/UEFI_PCI_ENHANCE-2
> > > > > PATCH
> > > > > > > > > 05/12]
> > > > > > > > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > > > > > > >
> > > > > > > > > Thanks for the review, Ray!
> > > > > > > > > My response in line
> > > > > > > > >
> > > > > > > > > > -----Original Message-----
> > > > > > > > > > From: Ni, Ray <ray.ni@intel.com>
> > > > > > > > > > Sent: Tuesday, December 17, 2019 5:26 PM
> > > > > > > > > > To: Javeed, Ashraf <ashraf.javeed@intel.com>;
> > > > > > > > > > devel@edk2.groups.io
> > > > > > > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > > > > > > <hao.a.wu@intel.com>
> > > > > > > > > > Subject: RE: [edk2-devel]
> > > > > > > > > > [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > > > > > > > > 05/12]
> > > > > > > > > > PciBusDxe: Setup sub-phases for PCI feature
> > > > > > > > > > enumeration
> > > > > > > > > >
> > > > > > > > > > Please check comments below.
> > > > > > > > > > I may have more comments regarding to the four phases
> > > > > > > > > > after I finish
> > > > > > > > > review of
> > > > > > > > > > further patches.
> > > > > > > > > >
> > > > > > > > > > Besides the comments below, I have a general comments
> > > > > > > > > > to the debug
> > > > > > > > > > message: can you please review the existing debug
> > > > > > > > > > message in the PciBus
> > > > > > > > > driver
> > > > > > > > > > and make sure your newly added debug message aligns to
> > > > > > > > > > existing
> > > > > > > style.
> > > > > > > > > And try
> > > > > > > > > > to use less lines of debug messages with still enough
> > > > > > > > > > debug
> > > > > > > information.
> > > > > > > > > Ok, will look into that.
> > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > > > +PRIMARY_ROOT_PORT_NODE
> > > > > > > *mPrimaryRootPortList;
> > > > > > > > > > > > +
> > > > > > > > > > > > +/**
> > > > > > > > > > > > +  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;
> > > > > > > > > >
> > > > > > > > > > 1. Please follow existing linked list usage style. The
> > > > > > > > > > first node in the list is an empty header node.
> > > > > > > > > >
> > > > > > > > > > LIST_ENTRY   mPrimaryRootPortList;
> > > > > > > > > > LIST_ENTRY   mPciFeaturesConfigurationCompletionList;
> > > > > > > > > >
> > > > > > > > > Ok, will make the change when I incorporate the ECR 0.75
> > > > > > > > > or greater
> > > > > > > version.
> > > > > > > > >
> > > > > > > > > > > > +BOOLEAN
> > > > > > > > > > > > +CheckPciFeatureConfigurationRecordExist (
> > > > > > > > > > > > +  IN  PCI_IO_DEVICE                             *RootBridge,
> > > > > > > > > > > > +  OUT
> > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > > > > > > > > > +**PciFeatureConfigRecord
> > > > > > > > > > > > +  )
> > > > > > > > > >
> > > > > > > > > > 2. Is this function to check whether the PCIE features
> > > > > > > > > > under a root bridge is already initialized?
> > > > > > > > > > Can you use the existing variable gFullEnumeration?
> > > > > > > > > > The variable is set to TRUE when the enumeration is
> > > > > > > > > > done to a host bridge
> > > > > > > > > in the
> > > > > > > > > > first time.
> > > > > > > > > > By using gFullEnumeration, the entire function is not
> needed.
> > > > > > > > > >
> > > > > > > > > Ok, will look into this.
> > > > > > > > >
> > > > > > > > > > > > +EFI_STATUS
> > > > > AddRootBridgeInPciFeaturesConfigCompletionList (
> > > > > > > > > > > > +  IN PCI_IO_DEVICE          *RootBridge,
> > > > > > > > > > > > +  IN BOOLEAN                ReEnumerationRequired
> > > > > > > > > > > > +  )
> > > > > > > > > >
> > > > > > > > > > 3. Same question as #2. I think by using
> > > > > > > > > > gFullEnumeration, this function is
> > > > > > > > > not
> > > > > > > > > > needed.
> > > > > > > > > >
> > > > > > > > > OK
> > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > > > +BOOLEAN
> > > > > > > > > > > > +IsPciRootPortEmpty (
> > > > > > > > > > > > +  IN  PCI_IO_DEVICE                           *PciDevice
> > > > > > > > > > > > +  )
> > > > > > > > > >
> > > > > > > > > > 4. Please use IsListEmpty() directly from callers and
> > > > > > > > > > remove this
> > > > > > > function.
> > > > > > > > > >
> > > > > > > > > Will consider this.
> > > > > > > > >
> > > > > > > > > > > > +**/
> > > > > > > > > > > > +EFI_STATUS
> > > > > > > > > > > > +EnumerateOtherPciFeatures (
> > > > > > > > > >
> > > > > > > > > > 5. Can it be "EnumeratePcieFeatures"?
> > > > > > > > > >
> > > > > > > > > Yes, with the change to ECR 0.75, this routine name
> > > > > > > > > shall be
> > > > > changed.
> > > > > > > > >
> > > > > > > > > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > > > > > > > > > +  )
> > > > > > > > > > > > +{
> > > > > > > > > > > > +  EFI_STATUS            Status;
> > > > > > > > > > > > +  UINTN                 OtherPciFeatureConfigPhase;
> > > > > > > > > > > > +
> > > > > > > > > > > > +  //
> > > > > > > > > > > > +  // check on PCI features configuration is
> > > > > > > > > > > > + complete and re-enumeration is required  //  if
> > > > > > > > > > > > + (!CheckPciFeaturesConfigurationRequired
> > > > > > > > > > > > + (RootBridge)) {
> > > > > > > > > > > > +    return EFI_ALREADY_STARTED;  }
> > > > > > > > > > > > +
> > > > > > > > > >  > > +  CHAR16                *Str;
> > > > > > > > > > > > +  Str = ConvertDevicePathToText (
> > > > > > > > > > > > +          DevicePathFromHandle (RootBridge->Handle),
> > > > > > > > > > > > +          FALSE,
> > > > > > > > > > > > +          FALSE
> > > > > > > > > > > > +        );
> > > > > > > > > > > > +  DEBUG ((DEBUG_INFO, "Enumerating PCI features
> > > > > > > > > > > > + for Root Bridge %s\n", Str != NULL ? Str :
> > > > > > > > > > > > + L""));
> > > > > > > > > >
> > > > > > > > > > 6. Please use DEBUG_CODE macro to include
> > > > > > > > > > ConvertDevicePathToText()
> > > > > > > > > and
> > > > > > > > > > DEBUG().
> > > > > > > > > > Please remember to call FreePool().
> > > > > > > > > >
> > > > > > > > > Ok, will can under DEBUG_CODE, and free pool is called
> > > > > > > > > in the end
> > > > > > > > >
> > > > > > > > > > > > +
> > > > > > > > > > > > +  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);
> > > > > > > > > >
> > > > > > > > > > 7. How about "RecordPciRootPorts (RootBridge)"? The
> > > "Bridges"
> > > > > > > > > > suffix is a
> > > > > > > > > bit
> > > > > > > > > > confusing.
> > > > > > > > > >
> > > > > > > > > Fine, will change.
> > > > > > > > >
> > > > > > > > > > > > +      case  PciFeatureGetDevicePolicy:
> > > > > > > > > > > > +      case  PciFeatureSetupPhase:
> > > > > > > > > >
> > > > > > > > > > 8. In SetupPciFeatures(), why do you need to call
> > DeviceExist()?
> > > > > > > > > > Did you see any case that a device is detected in the
> > > > > > > > > > beginning of PciBus
> > > > > > > > > scan
> > > > > > > > > > but is hidden when calling SetupPciFeatures()?
> > > > > > > > > >
> > > > > > > > > Yes, that is the case; device detected during the
> > > > > > > > > beginning of PciBus scan appears to be hidden by the
> > > > > > > > > platform drivers, since numerous legacy callbacks are
> > > > > > > > > initiated at different phase of PCI enumeration to the
> > > > > > > > > PCI Host Bridge, and
> > > PciPlatform drivers.
> > > > > > > > > This can be avoided if the PciBus driver is enhanced to
> > > > > > > > > check for PCI device existence before the publication of
> > > > > > > > > the PCI IO Protocol, and removal of the PCI_IO_DEVICE
> > > > > > > > > instance from the
> > > > > linked list.
> > > > > > > > >
> > > > > > > > > > 9. In GetPciFeaturesConfigurationTable() when checking
> > > > > > > > > > whether a PCI
> > > > > > > > > device
> > > > > > > > > > belongs to a root port, we can use below simpler logic:
> > > > > > > > > >   SizeOfPciDevicePath = GetDevicePathSize (PciDevicePath);
> > > > > > > > > >   SizeOfRootPortDevicePath = GetDevicePathSize
> > > (RootPortPath);
> > > > > > > > > >   if ((SizeOfRootPortDevicePath < SizeOfPciDevicePath) &&
> > > > > > > > > >       CompareMem (PciDevicePath, RootPortPath,
> > > > > > > > > SizeOfRootPortDevicePath -
> > > > > > > > > > END_DEVICE_PATH_LENGTH) == 0)) {
> > > > > > > > > >     // PCI device belongs to the root port.
> > > > > > > > > >   }
> > > > > > > > > >
> > > > > > > > > Ok.
> > > > > > > > >
> > > > > > > > > > > > +        Status = ProgramPciFeatures (RootBridge);
> > > > > > > > > > 10. ProgramPcieFeatures()?
> > > > > > > > > >
> > > > > > > > > OK
> > > > > > > > >
> > > > > > > > > > > > +
> > > > > > > > > > > > +  if (Str != NULL) {
> > > > > > > > > > > > +    FreePool (Str);  }
> > > > > > > > > >
> > > > > > > > > > 11. OK the Str is freed here because Str is needed for
> > > > > > > > > > other debug
> > > > > > > > > messages
> > > > > > > > > > inside the function.
> > > > > > > > > >
> > > > > > > > > Yes
> > > > > > > > >
> > > > > > > > > > > > +  //
> > > > > > > > > > > > +  // mark this root bridge as PCI features
> > > > > > > > > > > > +configuration complete, and no new
> > > > > > > > > > > > +  // enumeration is required
> > > > > > > > > > > > +  //
> > > > > > > > > > > > +  AddRootBridgeInPciFeaturesConfigCompletionList
> > > > > > > > > > > > +(RootBridge, FALSE);
> > > > > > > > > >
> > > > > > > > > > 12. Not needed.
> > > > > > > > > >
> > > > > > > > > ok, after incorporating the logic of gFullEnumeration it
> > > > > > > > > won't be required
> > > > > > > > >
> > > > > > > > > > > > +_PRIMARY_ROOT_PORT_NODE {
> > > > > > > > > >
> > > > > > > > > > > > +  //
> > > > > > > > > > > > +  // Signature header
> > > > > > > > > > > > +  //
> > > > > > > > > > > > +  UINT32                                    Signature;
> > > > > > > > > > > > +  //
> > > > > > > > > > > > +  // linked list pointers to next node
> > > > > > > > > > > > +  //
> > > > > > > > > > > > +  LIST_ENTRY                                NeighborRootPort;
> > > > > > > > > > > > +  //
> > > > > > > > > > > > +  // pointer to PCI_IO_DEVICE of the primary PCI
> > > > > > > > > > > > +Controller device
> > > > > > > > > > > > +  //
> > > > > > > > > > > > +  EFI_DEVICE_PATH_PROTOCOL
> > > > > *RootPortDevicePath;
> > > > > > > > > > > > +  //
> > > > > > > > > > > > +  // pointer to the corresponding PCI feature
> > > > > > > > > > > > +configuration Table node
> > > > > > > > > > > > +  // all the child PCI devices of the controller
> > > > > > > > > > > > +are aligned based on this table
> > > > > > > > > > > > +  //
> > > > > > > > > > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > > > > > > > *OtherPciFeaturesConfigurationTable;
> > > > > > > > > > > > +};
> > > > > > > > > >
> > > > > > > > > > 13. Can you add the
> > > > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > > field
> > > > > > > > > to
> > > > > > > > > > PCI_IO_DEVICE structure?
> > > > > > > > > > So this structure PRIMARY_ROOT_PORT_NODE is not
> > needed.
> > > > > > > > > >
> > > > > > > > > I think it is better to maintain separately as this
> > > > > > > > > configuration table is confined to a group of PCI
> > > > > > > > > devices and for the RCiEP it is not applicable hence not
> required.
> > > > > > > > > Moreover, I am maintaining a variable for each PCIe
> > > > > > > > > feature in the PCI_IO_DEVICE; perhaps I can
> > > > > > > consider having just pointer of it....
> > > > > > > > >
> > > > > > > > > > > > +struct
> > > _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
> > > > > > > > > > 14. This structure is not needed if using gFullEnumeration.
> > > > > > > > > Yes.
> > > > > > > >
> > > > > > > > 


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

* Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
  2020-04-21  6:22                         ` Javeed, Ashraf
@ 2020-05-08  8:26                           ` Ni, Ray
  0 siblings, 0 replies; 51+ messages in thread
From: Ni, Ray @ 2020-05-08  8:26 UTC (permalink / raw)
  To: Javeed, Ashraf, devel@edk2.groups.io; +Cc: Wang, Jian J, Wu, Hao A

Ashraf,
Thanks for the reply. Inline comments below.

> -----Original Message-----
> From: Javeed, Ashraf <ashraf.javeed@intel.com>
> Sent: Tuesday, April 21, 2020 2:22 PM
> To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A <hao.a.wu@intel.com>
> Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature
> enumeration
> 
> About the "AtomicOp", I want to retract about the check for the Routing Capability to set the platform policy about the blocking
> the AtomicOp requests. The implementation seems good.
> 
> Thanks
> Ashraf
> 
> > -----Original Message-----
> > From: Javeed, Ashraf
> > Sent: Tuesday, April 21, 2020 11:33 AM
> > To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > <hao.a.wu@intel.com>
> > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
> >
> > About the "CompletionTimeout ", I want to retract about the AUTO option;
> > the implementation is good and device initialization should be skipped for
> > this option.
> >
> > Regards
> > Ashraf
> >
> > > -----Original Message-----
> > > From: Javeed, Ashraf <ashraf.javeed@intel.com>
> > > Sent: Monday, April 20, 2020 6:53 PM
> > > To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > <hao.a.wu@intel.com>; Javeed, Ashraf <ashraf.javeed@intel.com>
> > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > > 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
> > >
> > > Ray,
> > > Sorry for late response as I got into other priorities. Let's try to
> > > finish this ASAP.
> > > Certainly the implementation of yours has reduced the code size in
> > > great deal by deprecating the EFI encodings for the PCIe features, and
> > > using the actual HW values along with the global definition of AUTO
> > > and NOT_APPLICABLE (as an alias to DO_NOT_TOUCH). I am concerned
> > that
> > > lot of explanation in the text of the PCI Express Protocol has to be
> > > provided about the rules that platform FW developer has to follow
> > > w.r.t. AUTO and DO_NOT_TOUCH in the GetDevicePolicy(); that needs to
> > > be published in the PI Specification. I shall take your implementation
> > > and add the other 3 PCIe features that I had implemented (ExtendedTag,
> > > Aspm,
> > > CommonClockConfiguration) into this scheme, and also provide how
> > these
> > > global options rules can be defined for the other non-implemented PCIe
> > > features.
> > > However, I have other suggestions/corrections for the present 7 PCIe
> > > features implementation, which I want to discuss by highlighting the
> > > platform policy of AUTO and DO_NOT_DISTURB.
> > >
> > > (1) MaxPayloadSize:- This feature requires aligning all the PCI
> > > devices in the hierarchy to have a common value. (The device policy by
> > > platform shall be used to align with all the devices in hierarchy
> > > based on their capability, thus value less than capability shall
> > > result in all devices in hierarchy supporting that value in capability to be
> > programmed).
> > > 	(a) AUTO: The DeviceCapability.MaxPayloadSize value is considered
> > > while scan all the nodes in the hierarchy
> > > 	(b) DO_NOT_TOUCH: Should be considered as invalid value to skip
> > for
> > > this feature. Two options in this scenario...
> > > 		(i) The PciBusDxe shall use this option to force the HW
> > default
> > > value of 128B

1. Platform can set MaxPayloadSize policy value to 128B if platform wants
to force to use 128B.
Why do you think skipping this feature is invalid?



> > > 		(ii) Behave same as AUTO.
> > > 	I vote for option (i) above.
> > >
> > > (2) MaxReadReqSize:- Does not need all the devices in hierarchy to be
> > > align to common value. However, the spec imposes that for an
> > > isochronous configured device its memory read request should be equal
> > > to MayPayloadSize; thus I accept your implementation since determining
> > > whether that device in Isochronous mode is beyond the scope of
> > PciBusDxe
> > > 	(a) AUTO: MaxReadReqSize = MaxPayloadSize; shall cover the device
> > > configured in Isochronous case.
> > > 	(b) DO_NOT_TOUCH: skip programming the DeviceControl register
> > of the
> > > device

2. I take your answer as an agreement😊

> > >
> > > (3) RelaxOrdering:- Specific to device to enable or disable; does not
> > > require any coherency with all the devices in the hierarchy
> > > 	(a) AUTO: device initialization is skipped
> > > 	(b) DO_NOT_TOUCH: device initialization is skipped

3. Agreement.

> > >
> > > (4) NoSnoop:- Specific to device to enable or disable; does not
> > > require any coherency with all the devices in the hierarchy
> > > 	(a) AUTO: device initialization is skipped
> > > 	(b) DO_NOT_TOUCH: device initialization is skipped

4. Agreement.

> > >
> > > (5) CompletionTimeout:-  The range and detection mechanism disable can
> > > be set specifically for any device; does not require to be aligned
> > > with all devices in the hierarchy
> > > 	(a) AUTO: your implementation ignores it (same as do not touch); I
> > > propose that platform can provide this option to set the
> > > DeviceControl2.CompletionTimeoutValue as per its high range value of
> > > DeviceCapability2.CompletionTimeoutRangesSupported, ignoring the
> > > CompletionTimeoutDisableSupported. For example; if the
> > > DeviceCapability2 supports Ranges A, B, C and D; than its
> > > DeviceControl2.CompletionTimeoutValue can be programmed to 1110b
> > (17s
> > > to 64s) for higher subrange.

5. Based on your latest reply, I consider you agree to skip this feature for AUTO.


> > > 	(b) DO_NOT_TOUCH: device initialization is skipped
> > > 	Your implementation about the device policy from platform appears
> > OK
> > > to me.
> > >
> > > (6) Ltr: As per PCIe specification, the LTR capability is provided for
> > > all the PCI devices, disabled by default, and if LTR needs to be
> > > enabled for Endpoint device than all the in-between component from
> > > Root Port to Endpoint needs to be enabled, and it is not required that
> > > all Endpoints have to be LTR enabled.
> > > 	(a) AUTO: as per your implementation, this option is ignored as
> > > invalid, and overwritten with its child device and if no valid for
> > > child device than device initialization is skipped
> > > 	(b) DO_NOT_TOUCH: as per your implementation, this option is
> > ignored
> > > as invalid. and overwritten with its child device and if no valid for
> > > child device than device initialization is skipped
> > > 	Why does your implementation consider changing only the parent
> > N as
> > > per its child N+1, and not vice versa? If platform only updates the
> > > Root port (RP) and not the Endpoint device than this implementation
> > > only programs the RP, right?

6.1. Right.

> > > 	In real scenario, the platform FW does not provide the policy for
> > > PCIe Endpoint devices mounted on the PCIe slots since those policies
> > > are statically defined to the fixed components of the chip. Thus,
> > > platform expects enabling the PCIe Root Port LTR mechanism, in hope
> > > that its valid PCIe Endpoint device gets enabled if all the devices
> > > are capable of LTR mechanism.

6.2. That's what I am not sure about. In real scenario, LTR is requested by
end point device driver. When PciBus receives the request, it checks all devices
between the root complex and the end point and enables the LTR in the whole path if
all devices in the path are capable of LTR.

The PCIE_PLATFORM protocol is useful to provide policy for fixed components
of the chip.



> > > 	I propose, even if platform provides one device to be LTR enable in
> > > the path from Root Port to Endpoint device, than PciBusDxe can enable
> > > all the devices in the path if all are LTR capable. This shall be also
> > > for Switch with multiple downstream ports with each port connected to
> > > independent Endpoint devices, if platform provide LTR enable to Root
> > > Port than enable for each path of devices if the downstream port's
> > > Endpoint device is LTR capable. If any one downstream port's Endpoint
> > > device is not capable than it need not set for that device.

6.3. Let me confirm my understanding. You are saying:
if platform policy wants any individual device between root complex and the
end point to enable LTR, PciBus driver enables LTR for all downside child devices and
all upside devices in the path to root complex.
In the following device tree, if platform policy for switch#2 is TRUE, PciBus enables LTR
for
a. switch#2
b. EP#2 and EP#3
c. switch#1.downstream that connects to switch#2.upstream, 
d. switch#1.upstream

RootComplex
          |
    switch#1
      /       \
EP#1    switch#2
              /         \
         EP#2     EP#3


I don't agree with this interpretation of platform policy. The policy is for individual
pcie device. If platform wants PciBus to enable LTR for certain devices, it should
set the policy to TRUE for those devices. In above device tree, platform needs to
return TRUE for devices #a, #b, #c, #d.
 
> > >
> > > (7) AtomicOp: As per PCIe specification, the DeviceControl2 register
> > > provides the AtomicOp Requester Enable bit (6) and blocking of
> > > AtomicOp request bit (7) for the Port device.
> > > 	The AtomicOp requester capability determination is out of scope,
> > > hence it can be just relied on platform policy request. However, the
> > > blocking AtomicOp request on the port device depends on the Device
> > > Routing capability bit defined in the DeviceCapability2 register.
> > > 	(a) AUTO: device initialization is skipped
> > > 	(b) DO_NOT_TOUCH: device initialization is skipped
> > > 	I think the change required in this implementation is the check for
> > > the Routing Capability to enable the blocking of AtomicOp request for
> > > the port device; do you agree?

7. Based on your latest reply, I think my proposed implementation is ok to you.

> > >
> > > Thanks
> > > Ashraf
> > >
> > > > -----Original Message-----
> > > > From: Ni, Ray <ray.ni@intel.com>
> > > > Sent: Tuesday, March 17, 2020 9:07 PM
> > > > To: Javeed, Ashraf <ashraf.javeed@intel.com>; devel@edk2.groups.io
> > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > <hao.a.wu@intel.com>
> > > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > > > 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > >
> > > > Ashraf,
> > > > Thank you for the prompt response!
> > > >
> > > > My response in below.
> > > > (I removed some earlier conversations, but the context is still
> > > > kept.)
> > > >
> > > > > > I take it as an agree of using the global AUTO. Thanks for that.
> > > > > Please note that there is another request of "Do not touch", and I
> > > > > am still contemplating whether both AUTO and DO_NOT_TOUCH
> > > options
> > > > could
> > > > > be applicable to all the PCIe features or not. It could be
> > > > > possible to take
> > > > AUTO for some of them and DO_NOT_TOUCH for others. Need to
> > > consider
> > > > each PCIe feature separately for both these options.
> > > >
> > > >
> > > > I think we are basically aligned on this.
> > > > I agree that each PCIe feature should have clear statement about how
> > > > to interpret AUTO and DO_NOT_TOUCH.
> > > > DO_NOT_TOUCH in my code change is NOT_APPLICABLE.
> > > > If you check some of the features I already implemented, the
> > > > comments say clearly what AUTO and NOT_APPLICABLE mean for that
> > > > specific
> > > feature.
> > > > Looking forward to your comments on how to interpret AUTO and
> > > > NOT_APPLICABLE for each PCIe feature.
> > > >
> > > > > > Supposing a root bridge contains 1 RCiEP and two root ports, the
> > > > > > implementation ensures there will be 3 separate contexts for each.
> > > > > > As you can see, every time the code starts enumeration from a
> > > > > > RCiEP or a root port, a new Context[] is setup. Context[i] is
> > > > > > associated with the
> > > > feature _i_.
> > > > > >
> > > > > I realize now, that there are 3 nested for-loops in the
> > > > > EnumerateRootBridgePcieFeatures(), the first one enables the
> > > > > processing of first level nodes of the Root Bridge instance, and
> > > > > in this way
> > > > the context[i] used for each node will be valid as it covers each
> > > > node's hierarchy.
> > > >
> > > > I think we are aligned on this.
> > > >
> > > > > >
> > > > > > The level N and N+1 is needed for AtomicOp or Ltr feature (which
> > > > > > I need to go back to check the code).
> > > > > > I want to avoid the individual feature scan/program routine
> > > > > > checks device's parent/children.
> > > > > > I understand that in PCIE spec, a switch consists of an upstream
> > > > > > port and several downstream ports.
> > > > > > It means a switch populates a bridge which connects to the
> > > > > > upstream and several bridges under the upstream bridge which
> > > > > > connect to the downstream.
> > > > > > But from software perspective, I don't think we should care
> > > > > > about
> > > that.
> > > > > > Maybe I am wrong. Can you please give a real example that
> > > > > > treating in my way would cause some issues?
> > > > > >
> > > > > Let just say we have PCIe switch connected to Root Port on a host,
> > > > > and it has 2 downstream ports, each connected to one Endpoint
> > > > > device
> > > each.
> > > > > Platform has selected to enable LTR for second downstream port's
> > > > > endpoint device, not both. As per your code logic of LTR, where
> > > > > you use the N and N+1 to compare between the parent and child,
> > > > > will not be
> > > > applicable if you use the same condition to check downstream port
> > > > (N+1), and its parent upstream port, because N would be the Endpoint
> > > > device of first downstream port of the PCIe switch and not its
> > > > upstream
> > > port.
> > > > > Root Port ->					1|0|0
> > > > > Switch upstream port ->				2|0|0 (M-1)
> > > > > Switch downstream ports ->	3|0|0,(M)		5|0|0 (N
> > > (=M+2))
> > > > > Endpoint devices ->		4|0|0 (M+1)		6|0|0 (N+1
> > > (=M+3))
> > > > > The level+1 logic when the EnumeratePcieDevices() is called
> > > > > recursively, will result in one value greater than the Endpoint
> > > > > device for
> > > > the second downstream port.
> > > >
> > > > The level value in my code will be:
> > > > Root Port ->					1|0|0 (level 0)
> > > > Switch upstream port ->				2|0|0 (level 1)
> > > > Switch downstream ports ->	3|0|0,(level 2)		5|0|0,(level
> > 2)
> > > > Endpoint devices ->		4|0|0,(level 3)		6|0|0,(level
> > 3)
> > > >
> > > > Level of device 5|0|0 is still 2, not 4.
> > > >
> > > > I also did the unit test to ensure the LTR feature logic is good.
> > > >
> > > > For below device hierarchy with LTR enabled in 5/0/0 and 11/0/0,
> > > > disabled in 9/0/0 The LTR setting for upstream bridges should be as
> > > following:
> > > >                     0/4/0[LTR:1]
> > > >   2/0/0[1]  |       2/1/0[1]         | 2/2/0[0]
> > > >   3/0/0[1]  |       7/0/0[1]
> > > >   4/0/0[1]  |       8/0/0[1]
> > > >   5/0/0[1]  | 9/0/0[0]   9/1/0[1]
> > > >                          10/0/0[1]
> > > >                          11/0/0[1]
> > > >
> > > > The unit test code is in commit "Test case for LTR".
> > > >
> > > > >
> > > > > > >
> > > > > > > I liked the Pre & Post order flag that is used to processing
> > > > > > > parent-to-child
> > > > > > vs. child-to-parent nodes.
> > > > > >
> > > > > > Actually I didn't have this flag in the first version of my code
> > > > > > change. But later I found it's needed for some features like LTR
> > > > > > which needs to be programmed from rootbridge to endpoint
> > > according
> > > > to spec.
> > > > > >
> > > > > >
> > > > > > > You are calling the first
> > > > > > > and last features as fakes, when you actually parse all the
> > > > > > > nodes for the GetDevicePolicy() and NotifyDeviceState(); to me
> > > > > > > it is actually an un-named phase where all the nodes are
> > > > > > > queried or informed to the
> > > > > > platform; that seems fine to save the NULL on the
> > > > > > mPcieFeatures[]
> > > > table.
> > > > > >
> > > > > > Yes I put GetDevicePolicy() and NotifyDeviceState() in the
> > > > > > feature array in my first version of code. And later I called
> > > > > > the two separately for better code readability. But it was my
> > > > > > fault that I didn't update the commit message. It caused confusion
> > to you.
> > > > > >
> > > > > > >
> > > > > > > Thanks
> > > > > > > Ashraf
> > > > > > >
> > > > > > > > -----Original Message-----
> > > > > > > > From: Ni, Ray <ray.ni@intel.com>
> > > > > > > > Sent: Thursday, March 5, 2020 7:43 PM
> > > > > > > > To: devel@edk2.groups.io; Ni, Ray <ray.ni@intel.com>;
> > > > > > > > Javeed, Ashraf <ashraf.javeed@intel.com>
> > > > > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > > > > <hao.a.wu@intel.com>
> > > > > > > > Subject: RE: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2
> > > > PATCH
> > > > > > > > 05/12] PciBusDxe: Setup sub-phases for PCI feature
> > > > > > > > enumeration
> > > > > > > >
> > > > > > > > Ashraf,
> > > > > > > > I think it might be better to describe my review comments
> > > > > > > > with code implementation.
> > > > > > > > Can you please check this branch where I did some
> > > > > > > > modification based on your code?
> > > > > > > > https://github.com/niruiyu/edk2/tree/pci/pcie2
> > > > > > > >
> > > > > > > > Let's firstly align on the feature initialization framework
> > > > > > implementation.
> > > > > > > > To be specific, this commit:
> > > > > > > > MdeModulePkg/PciBus: Add the framework to init PCIE features
> > > > > > > >
> > > > > >
> > > >
> > >
> > https://github.com/niruiyu/edk2/commit/9fb9a3dcef06de98a76825e2fc0
> > > > > > > > 7167446ee6fd9
> > > > > > > >
> > > > > > > > Thanks,
> > > > > > > > Ray
> > > > > > > >
> > > > > > > > > -----Original Message-----
> > > > > > > > > From: devel@edk2.groups.io <devel@edk2.groups.io> On
> > > > > > > > > Behalf
> > > > Of
> > > > > > Ni,
> > > > > > > > Ray
> > > > > > > > > Sent: Thursday, December 19, 2019 1:49 PM
> > > > > > > > > To: Javeed, Ashraf <ashraf.javeed@intel.com>;
> > > > > > > > > devel@edk2.groups.io
> > > > > > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > > > > > <hao.a.wu@intel.com>
> > > > > > > > > Subject: Re: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2
> > > > > > > > > PATCH 05/12]
> > > > > > > > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > > > > > > >
> > > > > > > > > After I reviewed the patch of enabling MaxPayloadSize,
> > > > > > > > > MaxReadReqSize and more PCIE features, I can now
> > > > > > > > > understand the phases more than earlier.
> > > > > > > > >
> > > > > > > > > Your patch proposed five phases:
> > > > > > > > >   //
> > > > > > > > >   // 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
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > I have several comments to the five phases.
> > > > > > > > > 1. Scan phase is not do the scanning but creates a list to
> > > > > > > > > hold all root ports under the root bridge.
> > > > > > > > > 2. Root ports collection is not required by all of the
> > > > > > > > > features, only by MPS and MRRS.
> > > > > > > > > But the collection always happens even when platform
> > > > > > > > > doesn't require PciBus to initialize MPS or MRRS.
> > > > > > > > > 3. GetDevicePolicy phase is not just call the
> > > > > > > > > GetDevicePolicy for each device. It also reads the PCIE
> > > > > > > > > configuration space to get the device's feature related
> > > > > > > > > capabilities, for some of the
> > > > features.
> > > > > > > > >
> > > > > > > > > With that, I propose to define 4 phases:
> > > > > > > > > 1. Initialize phase
> > > > > > > > > This phase is similar to your Scan phase.
> > > > > > > > > For some features, this phase does nothing.
> > > > > > > > > For MPS and MRRS, this phase creates a list holding all
> > > > > > > > > root
> > > ports.
> > > > > > > > >
> > > > > > > > > 2. Scan phase
> > > > > > > > > This phase is similar to your GetDevicePolicy phase.
> > > > > > > > > For some features, this phase needs nothing do to.
> > > > > > > > > For MPS and MRRS, this phase scan all devices and get the
> > > > > > > > > aligned value of MPS or MRRS.
> > > > > > > > >
> > > > > > > > > 3. Program phase or Configuration phase This phase is
> > > > > > > > > similar to your Configuration phase.
> > > > > > > > > The Setup phase can be merged to this phase.
> > > > > > > > >
> > > > > > > > > 4. Finalize phase.
> > > > > > > > > This phase is similar to your ConfigurationComplete phase.
> > > > > > > > > This phase frees the resources occupied/allocated in
> > > > > > > > > Initialize
> > > > phase.
> > > > > > > > > For some of the features, this phase may do nothing.
> > > > > > > > >
> > > > > > > > > Each feature needs to provide function pointers for each
> > > > > > > > > phase and NULL means the feature doesn't need to do
> > > > > > > > > anything in the specific phase.
> > > > > > > > > With that, we can define a structure:
> > > > > > > > > Typedef struct {
> > > > > > > > >   BOOLEAN                          Enable;
> > > > > > > > >   PCIE_FEATURE_INITILAIZE Initialize;
> > > > > > > > >   PCIE_FEATURE_SCAN  Scan;
> > > > > > > > >   PCIE_FEATURE_PROGRAM Program;
> > > > > > > > >   PCIE_FEATURE_FINALIZE Finalize; } PCIE_FEATURE_ENTRY;
> > > > > > > > >
> > > > > > > > > With that, we can define a module level global variable:
> > > > > > > > > PCIE_FEATURE_ENTRY mPcieFeatures[] = {
> > > > > > > > >   { TRUE, MaxPayloadInitialize, MaxPayloadScan,
> > > > > > > > > MaxPayloadProgram, MaxPayloadFinalize},
> > > > > > > > >   { TRUE, MaxReadRequestInitialize, MaxReadRequestScan,
> > > > > > > > > MaxReadRequestProgram, MaxReadRequestFinalize},
> > > > > > > > >   { TRUE, NULL, NULL, RelaxOrderProgram, NULL},
> > > > > > > > >   { TRUE, NULL, CompletionTimeoutScan,
> > > > > > > > > CompletionTimeoutProgram,
> > > > > > > > NULL },
> > > > > > > > >   ...
> > > > > > > > > };
> > > > > > > > >
> > > > > > > > > PCIE_FEATURE_ENTRY.Enable can be set to FALSE according to
> > > > > > > > > the platform policy.
> > > > > > > > >
> > > > > > > > > The enable of PCIE features can be written as a feature
> > > > > > > > > agnostic for-
> > > > > > loop.
> > > > > > > > > This can make the new feature enabling code easy to add
> > > > > > > > > and
> > > > review.
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > > -----Original Message-----
> > > > > > > > > > From: Javeed, Ashraf <ashraf.javeed@intel.com>
> > > > > > > > > > Sent: Wednesday, December 18, 2019 3:14 PM
> > > > > > > > > > To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io
> > > > > > > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > > > > > > <hao.a.wu@intel.com>
> > > > > > > > > > Subject: RE: [edk2-devel]
> > > > > > > > > > [edk2-staging/UEFI_PCI_ENHANCE-2
> > > > > > PATCH
> > > > > > > > > > 05/12]
> > > > > > > > > > PciBusDxe: Setup sub-phases for PCI feature enumeration
> > > > > > > > > >
> > > > > > > > > > Thanks for the review, Ray!
> > > > > > > > > > My response in line
> > > > > > > > > >
> > > > > > > > > > > -----Original Message-----
> > > > > > > > > > > From: Ni, Ray <ray.ni@intel.com>
> > > > > > > > > > > Sent: Tuesday, December 17, 2019 5:26 PM
> > > > > > > > > > > To: Javeed, Ashraf <ashraf.javeed@intel.com>;
> > > > > > > > > > > devel@edk2.groups.io
> > > > > > > > > > > Cc: Wang, Jian J <jian.j.wang@intel.com>; Wu, Hao A
> > > > > > > > > > > <hao.a.wu@intel.com>
> > > > > > > > > > > Subject: RE: [edk2-devel]
> > > > > > > > > > > [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH
> > > > > > > > > > 05/12]
> > > > > > > > > > > PciBusDxe: Setup sub-phases for PCI feature
> > > > > > > > > > > enumeration
> > > > > > > > > > >
> > > > > > > > > > > Please check comments below.
> > > > > > > > > > > I may have more comments regarding to the four phases
> > > > > > > > > > > after I finish
> > > > > > > > > > review of
> > > > > > > > > > > further patches.
> > > > > > > > > > >
> > > > > > > > > > > Besides the comments below, I have a general comments
> > > > > > > > > > > to the debug
> > > > > > > > > > > message: can you please review the existing debug
> > > > > > > > > > > message in the PciBus
> > > > > > > > > > driver
> > > > > > > > > > > and make sure your newly added debug message aligns to
> > > > > > > > > > > existing
> > > > > > > > style.
> > > > > > > > > > And try
> > > > > > > > > > > to use less lines of debug messages with still enough
> > > > > > > > > > > debug
> > > > > > > > information.
> > > > > > > > > > Ok, will look into that.
> > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > > > > +PRIMARY_ROOT_PORT_NODE
> > > > > > > > *mPrimaryRootPortList;
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +/**
> > > > > > > > > > > > > +  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;
> > > > > > > > > > >
> > > > > > > > > > > 1. Please follow existing linked list usage style. The
> > > > > > > > > > > first node in the list is an empty header node.
> > > > > > > > > > >
> > > > > > > > > > > LIST_ENTRY   mPrimaryRootPortList;
> > > > > > > > > > > LIST_ENTRY   mPciFeaturesConfigurationCompletionList;
> > > > > > > > > > >
> > > > > > > > > > Ok, will make the change when I incorporate the ECR 0.75
> > > > > > > > > > or greater
> > > > > > > > version.
> > > > > > > > > >
> > > > > > > > > > > > > +BOOLEAN
> > > > > > > > > > > > > +CheckPciFeatureConfigurationRecordExist (
> > > > > > > > > > > > > +  IN  PCI_IO_DEVICE                             *RootBridge,
> > > > > > > > > > > > > +  OUT
> > > PCI_FEATURE_CONFIGURATION_COMPLETION_LIST
> > > > > > > > > > > > > +**PciFeatureConfigRecord
> > > > > > > > > > > > > +  )
> > > > > > > > > > >
> > > > > > > > > > > 2. Is this function to check whether the PCIE features
> > > > > > > > > > > under a root bridge is already initialized?
> > > > > > > > > > > Can you use the existing variable gFullEnumeration?
> > > > > > > > > > > The variable is set to TRUE when the enumeration is
> > > > > > > > > > > done to a host bridge
> > > > > > > > > > in the
> > > > > > > > > > > first time.
> > > > > > > > > > > By using gFullEnumeration, the entire function is not
> > needed.
> > > > > > > > > > >
> > > > > > > > > > Ok, will look into this.
> > > > > > > > > >
> > > > > > > > > > > > > +EFI_STATUS
> > > > > > AddRootBridgeInPciFeaturesConfigCompletionList (
> > > > > > > > > > > > > +  IN PCI_IO_DEVICE          *RootBridge,
> > > > > > > > > > > > > +  IN BOOLEAN                ReEnumerationRequired
> > > > > > > > > > > > > +  )
> > > > > > > > > > >
> > > > > > > > > > > 3. Same question as #2. I think by using
> > > > > > > > > > > gFullEnumeration, this function is
> > > > > > > > > > not
> > > > > > > > > > > needed.
> > > > > > > > > > >
> > > > > > > > > > OK
> > > > > > > > > >
> > > > > > > > > > >
> > > > > > > > > > > > > +BOOLEAN
> > > > > > > > > > > > > +IsPciRootPortEmpty (
> > > > > > > > > > > > > +  IN  PCI_IO_DEVICE                           *PciDevice
> > > > > > > > > > > > > +  )
> > > > > > > > > > >
> > > > > > > > > > > 4. Please use IsListEmpty() directly from callers and
> > > > > > > > > > > remove this
> > > > > > > > function.
> > > > > > > > > > >
> > > > > > > > > > Will consider this.
> > > > > > > > > >
> > > > > > > > > > > > > +**/
> > > > > > > > > > > > > +EFI_STATUS
> > > > > > > > > > > > > +EnumerateOtherPciFeatures (
> > > > > > > > > > >
> > > > > > > > > > > 5. Can it be "EnumeratePcieFeatures"?
> > > > > > > > > > >
> > > > > > > > > > Yes, with the change to ECR 0.75, this routine name
> > > > > > > > > > shall be
> > > > > > changed.
> > > > > > > > > >
> > > > > > > > > > > > > +  IN PCI_IO_DEVICE          *RootBridge
> > > > > > > > > > > > > +  )
> > > > > > > > > > > > > +{
> > > > > > > > > > > > > +  EFI_STATUS            Status;
> > > > > > > > > > > > > +  UINTN                 OtherPciFeatureConfigPhase;
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +  //
> > > > > > > > > > > > > +  // check on PCI features configuration is
> > > > > > > > > > > > > + complete and re-enumeration is required  //  if
> > > > > > > > > > > > > + (!CheckPciFeaturesConfigurationRequired
> > > > > > > > > > > > > + (RootBridge)) {
> > > > > > > > > > > > > +    return EFI_ALREADY_STARTED;  }
> > > > > > > > > > > > > +
> > > > > > > > > > >  > > +  CHAR16                *Str;
> > > > > > > > > > > > > +  Str = ConvertDevicePathToText (
> > > > > > > > > > > > > +          DevicePathFromHandle (RootBridge->Handle),
> > > > > > > > > > > > > +          FALSE,
> > > > > > > > > > > > > +          FALSE
> > > > > > > > > > > > > +        );
> > > > > > > > > > > > > +  DEBUG ((DEBUG_INFO, "Enumerating PCI features
> > > > > > > > > > > > > + for Root Bridge %s\n", Str != NULL ? Str :
> > > > > > > > > > > > > + L""));
> > > > > > > > > > >
> > > > > > > > > > > 6. Please use DEBUG_CODE macro to include
> > > > > > > > > > > ConvertDevicePathToText()
> > > > > > > > > > and
> > > > > > > > > > > DEBUG().
> > > > > > > > > > > Please remember to call FreePool().
> > > > > > > > > > >
> > > > > > > > > > Ok, will can under DEBUG_CODE, and free pool is called
> > > > > > > > > > in the end
> > > > > > > > > >
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +  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);
> > > > > > > > > > >
> > > > > > > > > > > 7. How about "RecordPciRootPorts (RootBridge)"? The
> > > > "Bridges"
> > > > > > > > > > > suffix is a
> > > > > > > > > > bit
> > > > > > > > > > > confusing.
> > > > > > > > > > >
> > > > > > > > > > Fine, will change.
> > > > > > > > > >
> > > > > > > > > > > > > +      case  PciFeatureGetDevicePolicy:
> > > > > > > > > > > > > +      case  PciFeatureSetupPhase:
> > > > > > > > > > >
> > > > > > > > > > > 8. In SetupPciFeatures(), why do you need to call
> > > DeviceExist()?
> > > > > > > > > > > Did you see any case that a device is detected in the
> > > > > > > > > > > beginning of PciBus
> > > > > > > > > > scan
> > > > > > > > > > > but is hidden when calling SetupPciFeatures()?
> > > > > > > > > > >
> > > > > > > > > > Yes, that is the case; device detected during the
> > > > > > > > > > beginning of PciBus scan appears to be hidden by the
> > > > > > > > > > platform drivers, since numerous legacy callbacks are
> > > > > > > > > > initiated at different phase of PCI enumeration to the
> > > > > > > > > > PCI Host Bridge, and
> > > > PciPlatform drivers.
> > > > > > > > > > This can be avoided if the PciBus driver is enhanced to
> > > > > > > > > > check for PCI device existence before the publication of
> > > > > > > > > > the PCI IO Protocol, and removal of the PCI_IO_DEVICE
> > > > > > > > > > instance from the
> > > > > > linked list.
> > > > > > > > > >
> > > > > > > > > > > 9. In GetPciFeaturesConfigurationTable() when checking
> > > > > > > > > > > whether a PCI
> > > > > > > > > > device
> > > > > > > > > > > belongs to a root port, we can use below simpler logic:
> > > > > > > > > > >   SizeOfPciDevicePath = GetDevicePathSize (PciDevicePath);
> > > > > > > > > > >   SizeOfRootPortDevicePath = GetDevicePathSize
> > > > (RootPortPath);
> > > > > > > > > > >   if ((SizeOfRootPortDevicePath < SizeOfPciDevicePath) &&
> > > > > > > > > > >       CompareMem (PciDevicePath, RootPortPath,
> > > > > > > > > > SizeOfRootPortDevicePath -
> > > > > > > > > > > END_DEVICE_PATH_LENGTH) == 0)) {
> > > > > > > > > > >     // PCI device belongs to the root port.
> > > > > > > > > > >   }
> > > > > > > > > > >
> > > > > > > > > > Ok.
> > > > > > > > > >
> > > > > > > > > > > > > +        Status = ProgramPciFeatures (RootBridge);
> > > > > > > > > > > 10. ProgramPcieFeatures()?
> > > > > > > > > > >
> > > > > > > > > > OK
> > > > > > > > > >
> > > > > > > > > > > > > +
> > > > > > > > > > > > > +  if (Str != NULL) {
> > > > > > > > > > > > > +    FreePool (Str);  }
> > > > > > > > > > >
> > > > > > > > > > > 11. OK the Str is freed here because Str is needed for
> > > > > > > > > > > other debug
> > > > > > > > > > messages
> > > > > > > > > > > inside the function.
> > > > > > > > > > >
> > > > > > > > > > Yes
> > > > > > > > > >
> > > > > > > > > > > > > +  //
> > > > > > > > > > > > > +  // mark this root bridge as PCI features
> > > > > > > > > > > > > +configuration complete, and no new
> > > > > > > > > > > > > +  // enumeration is required
> > > > > > > > > > > > > +  //
> > > > > > > > > > > > > +  AddRootBridgeInPciFeaturesConfigCompletionList
> > > > > > > > > > > > > +(RootBridge, FALSE);
> > > > > > > > > > >
> > > > > > > > > > > 12. Not needed.
> > > > > > > > > > >
> > > > > > > > > > ok, after incorporating the logic of gFullEnumeration it
> > > > > > > > > > won't be required
> > > > > > > > > >
> > > > > > > > > > > > > +_PRIMARY_ROOT_PORT_NODE {
> > > > > > > > > > >
> > > > > > > > > > > > > +  //
> > > > > > > > > > > > > +  // Signature header
> > > > > > > > > > > > > +  //
> > > > > > > > > > > > > +  UINT32                                    Signature;
> > > > > > > > > > > > > +  //
> > > > > > > > > > > > > +  // linked list pointers to next node
> > > > > > > > > > > > > +  //
> > > > > > > > > > > > > +  LIST_ENTRY                                NeighborRootPort;
> > > > > > > > > > > > > +  //
> > > > > > > > > > > > > +  // pointer to PCI_IO_DEVICE of the primary PCI
> > > > > > > > > > > > > +Controller device
> > > > > > > > > > > > > +  //
> > > > > > > > > > > > > +  EFI_DEVICE_PATH_PROTOCOL
> > > > > > *RootPortDevicePath;
> > > > > > > > > > > > > +  //
> > > > > > > > > > > > > +  // pointer to the corresponding PCI feature
> > > > > > > > > > > > > +configuration Table node
> > > > > > > > > > > > > +  // all the child PCI devices of the controller
> > > > > > > > > > > > > +are aligned based on this table
> > > > > > > > > > > > > +  //
> > > > > > > > > > > > > +  OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > > > > > > > > *OtherPciFeaturesConfigurationTable;
> > > > > > > > > > > > > +};
> > > > > > > > > > >
> > > > > > > > > > > 13. Can you add the
> > > > > > OTHER_PCI_FEATURES_CONFIGURATION_TABLE
> > > > > > > > field
> > > > > > > > > > to
> > > > > > > > > > > PCI_IO_DEVICE structure?
> > > > > > > > > > > So this structure PRIMARY_ROOT_PORT_NODE is not
> > > needed.
> > > > > > > > > > >
> > > > > > > > > > I think it is better to maintain separately as this
> > > > > > > > > > configuration table is confined to a group of PCI
> > > > > > > > > > devices and for the RCiEP it is not applicable hence not
> > required.
> > > > > > > > > > Moreover, I am maintaining a variable for each PCIe
> > > > > > > > > > feature in the PCI_IO_DEVICE; perhaps I can
> > > > > > > > consider having just pointer of it....
> > > > > > > > > >
> > > > > > > > > > > > > +struct
> > > > _PCI_FEATURE_CONFIGURATION_COMPLETION_LIST {
> > > > > > > > > > > 14. This structure is not needed if using gFullEnumeration.
> > > > > > > > > > Yes.
> > > > > > > > >
> > > > > > > > > 


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

end of thread, other threads:[~2020-05-08  8:26 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-11-01 15:09 [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 00/12] New PCI features - MPS, MRRS, RO, NS, CTO Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe:New PCI features separation with PCD Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12] PciBusDxe: Reorganize the PCI Platform Protocol usage code Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12] PciBusDxe: Separation of the PCI device registration and start Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 04/12] PciBusDxe: Inclusion of new PCI Platform Protocol 2 Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 06/12] PciBusDxe: Integration of setup " Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] PciBusDxe: Record the PCI-Express Capability Structure Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12] PciBusDxe: New PCI feature Max_Payload_Size Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 09/12] PciBusDxe: New PCI feature Max_Read_Req_Size Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 10/12] PciBusDxe: New PCI feature Relax Ordering Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 11/12] PciBusDxe: New PCI feature No-Snoop Javeed, Ashraf
2019-11-01 15:09 ` [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 12/12] PciBusDxe: New PCI feature Completion Timeout Javeed, Ashraf
     [not found] ` <15D3127A726D26A6.7420@groups.io>
2019-11-13  3:22   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe:New PCI features separation with PCD Javeed, Ashraf
2019-12-16 12:46     ` Ni, Ray
     [not found] ` <15D3127AABF5037C.32624@groups.io>
2019-11-13  3:23   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12] PciBusDxe: Reorganize the PCI Platform Protocol usage code Javeed, Ashraf
2019-12-16 12:46     ` Ni, Ray
     [not found] ` <15D3127A98E21087.7420@groups.io>
2019-11-13  3:25   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12] PciBusDxe: Separation of the PCI device registration and start Javeed, Ashraf
2019-12-17  1:38     ` Ni, Ray
2019-12-17  3:19       ` Javeed, Ashraf
2019-12-19  1:34         ` Ni, Ray
2019-12-19  4:12           ` Javeed, Ashraf
     [not found] ` <15D3127AAE5DC481.32624@groups.io>
2019-11-13  3:26   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 04/12] PciBusDxe: Inclusion of new PCI Platform Protocol 2 Javeed, Ashraf
     [not found] ` <15D3127B934F51D3.12315@groups.io>
2019-11-13  3:27   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: Setup sub-phases for PCI feature enumeration Javeed, Ashraf
2019-12-17 11:56     ` Ni, Ray
2019-12-18  7:14       ` Javeed, Ashraf
2019-12-19  5:48         ` Ni, Ray
     [not found]         ` <15E1AFB3EABD031C.30484@groups.io>
2020-03-05 14:12           ` Ni, Ray
2020-03-16  9:33             ` Javeed, Ashraf
2020-03-16 14:00               ` Ni, Ray
2020-03-17  7:20                 ` Javeed, Ashraf
2020-03-17 15:36                   ` Ni, Ray
2020-04-20 13:22                     ` Javeed, Ashraf
2020-04-21  6:03                       ` Javeed, Ashraf
2020-04-21  6:22                         ` Javeed, Ashraf
2020-05-08  8:26                           ` Ni, Ray
     [not found] ` <15D3127BE430E7DA.31784@groups.io>
2019-11-13  3:28   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 06/12] PciBusDxe: Integration of setup " Javeed, Ashraf
2019-12-17 11:59     ` Ni, Ray
2019-12-18  7:15       ` Javeed, Ashraf
     [not found] ` <15D3127C6DFCD4A7.12315@groups.io>
2019-11-13  3:29   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] PciBusDxe: Record the PCI-Express Capability Structure Javeed, Ashraf
2019-12-17 12:03     ` Ni, Ray
2019-12-18  7:32       ` Javeed, Ashraf
     [not found] ` <15D3127D273722D4.32624@groups.io>
2019-11-13  3:30   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12] PciBusDxe: New PCI feature Max_Payload_Size Javeed, Ashraf
2019-12-18  8:38     ` Ni, Ray
2019-12-18  9:10       ` Ni, Ray
2019-12-18 14:35         ` Javeed, Ashraf
2019-12-19  2:14           ` Ni, Ray
     [not found] ` <15D3127DA6E2D860.7420@groups.io>
2019-11-13  3:31   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 09/12] PciBusDxe: New PCI feature Max_Read_Req_Size Javeed, Ashraf
     [not found] ` <15D3127E471DF360.32624@groups.io>
2019-11-13  3:32   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 10/12] PciBusDxe: New PCI feature Relax Ordering Javeed, Ashraf
     [not found] ` <15D3127EB6ED8506.12315@groups.io>
2019-11-13  3:33   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 11/12] PciBusDxe: New PCI feature No-Snoop Javeed, Ashraf
     [not found] ` <15D3127F5541064B.31784@groups.io>
2019-11-13  3:34   ` [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 12/12] PciBusDxe: New PCI feature Completion Timeout Javeed, Ashraf

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