From nobody Fri Apr 19 14:36:52 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+54064+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+54064+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1581105962176355.4729925580584; Fri, 7 Feb 2020 12:06:02 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id GtHeYY1788612xqei5M7Hzwn; Fri, 07 Feb 2020 12:06:01 -0800 X-Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web09.10520.1581105960932621955 for ; Fri, 07 Feb 2020 12:06:01 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Feb 2020 12:06:00 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,414,1574150400"; d="scan'208";a="225644120" X-Received: from unknown (HELO PIDSBABIOS005.gar.corp.intel.com) ([10.223.9.183]) by fmsmga007.fm.intel.com with ESMTP; 07 Feb 2020 12:05:56 -0800 From: "Javeed, Ashraf" To: devel@edk2.groups.io Cc: Jian J Wang , Hao A Wu , Ray Ni Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 01/12] MdeModulePkg/PciBusDxe: Setup for PCI Express features Date: Sat, 8 Feb 2020 01:34:36 +0530 Message-Id: <20200207200447.10536-2-ashraf.javeed@intel.com> In-Reply-To: <20200207200447.10536-1-ashraf.javeed@intel.com> References: <20200207200447.10536-1-ashraf.javeed@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ashraf.javeed@intel.com X-Gm-Message-State: fPPcftBL08GqP63nnfoi8rh2x1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1581105961; bh=Q7noTEk8O4Dm9afAUvFtHmTZhYtZs5jH0d2AG/1mig4=; h=Cc:Date:From:Reply-To:Subject:To; b=mdITvY/s/xaL238mtP93B5a0bfBspCmpTKVPCj6YIzMAK29T2hhUfLwlmdIBoS3b8eb LYKmN/jwvTRCiJNBXEQ3rNL0JRk1qkWeT78olYMpDknwc3W+ZHyG/PTT3BxY+o5+2A5G7 C0nPzXLpbem5wA2AFJuEm0EZuevJO05atko= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" References:- https://bugzilla.tianocore.org/show_bug.cgi?id=3D1954 https://bugzilla.tianocore.org/show_bug.cgi?id=3D2194 https://bugzilla.tianocore.org/show_bug.cgi?id=3D2313 https://bugzilla.tianocore.org/show_bug.cgi?id=3D2499 https://bugzilla.tianocore.org/show_bug.cgi?id=3D2500 This code change represents the preparation of common code setup for the new PCI Express features initialization, utilizing the new PCI Express Platform / Override Protocol. The new set of source files are as follows:- new file: /PciFeatureSupport.c new file: /PciFeatureSupport.h new file: /PciPlatformSupport.c new file: /PciPlatformSupport.h Signed-off-by: Ashraf Javeed Cc: Jian J Wang Cc: Hao A Wu Cc: Ray Ni --- MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c | 6 +++++- MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h | 12 ++++++++++-- MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf | 9 ++++++++- MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c | 12 +++++++++++- MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c | 891 ++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++++++++++++++++++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h | 226 ++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 302 ++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h | 87 ++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 1540 insertions(+), 5 deletions(-) diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c b/MdeModulePkg/Bus/Pci= /PciBusDxe/PciBus.c index b020ce5..714101c 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c @@ -8,7 +8,7 @@ PCI Root Bridges. So it means platform needs install PCI Root Bridge IO = protocol for each PCI Root Bus and install PCI Host Bridge Resource Allocation Protocol. =20 -Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent =20 **/ @@ -284,6 +284,10 @@ PciBusDriverBindingStart ( (VOID **) &gPciOverrideProtocol ); } + // + // get the PCI Express Protocol or the PCI Express Override Protocol + // + GetPciExpressProtocol (); =20 if (mIoMmuProtocol =3D=3D NULL) { gBS->LocateProtocol ( diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci= /PciBusDxe/PciBus.h index 504a1b1..225229d 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h @@ -1,7 +1,7 @@ /** @file Header files and data structures needed by PCI Bus module. =20 -Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent =20 **/ @@ -42,6 +42,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include +#include =20 typedef struct _PCI_IO_DEVICE PCI_IO_DEVICE; typedef struct _PCI_BAR PCI_BAR; @@ -79,6 +81,8 @@ typedef enum { #include "PciPowerManagement.h" #include "PciHotPlugSupport.h" #include "PciLib.h" +#include "PciPlatformSupport.h" +#include "PciFeatureSupport.h" =20 #define VGABASE1 0x3B0 #define VGALIMIT1 0x3BB @@ -263,9 +267,13 @@ struct _PCI_IO_DEVICE { =20 BOOLEAN IsPciExp; // - // For SR-IOV + // For PCI Express Capability List Structure // UINT8 PciExpressCapabilityOffset; + PCI_CAPABILITY_PCIEXP PciExpressCapabilityStructure; + // + // For SR-IOV + // UINT32 AriCapabilityOffset; UINT32 SrIovCapabilityOffset; UINT32 MrIovCapabilityOffset; diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf b/MdeModulePkg/Bu= s/Pci/PciBusDxe/PciBusDxe.inf index 05c2202..f06b411 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf @@ -2,7 +2,7 @@ # The PCI bus driver will probe all PCI devices and allocate MMIO and IO = space for these devices. # Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable hot= plug supporting. # -# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+# Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.
# # SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -57,6 +57,10 @@ PciCommand.h PciIo.h PciBus.h + PciFeatureSupport.c + PciFeatureSupport.h + PciPlatformSupport.c + PciPlatformSupport.h =20 [Packages] MdePkg/MdePkg.dec @@ -91,6 +95,9 @@ gEfiLoadFile2ProtocolGuid ## SOMETIMES_PRODUCES gEdkiiIoMmuProtocolGuid ## SOMETIMES_CONSUMES gEfiLoadedImageDevicePathProtocolGuid ## CONSUMES + gEfiPciExpressPlatformProtocolGuid ## SOMETIMES_CONS= UMES + gEfiPciExpressOverrideProtocolGuid ## SOMETIMES_CONS= UMES + =20 [FeaturePcd] gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport ## CON= SUMES diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c b/MdeMod= ulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c index c7eafff..c9e52ea 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c @@ -1,7 +1,7 @@ /** @file PCI emumeration support functions implementation for PCI Bus module. =20 -Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.
(C) Copyright 2015 Hewlett Packard Enterprise Development LP
SPDX-License-Identifier: BSD-2-Clause-Patent =20 @@ -2154,6 +2154,16 @@ CreatePciIoDevice ( ); if (!EFI_ERROR (Status)) { PciIoDevice->IsPciExp =3D TRUE; + // + // read the PCI device's entire PCI Express Capability structure + // + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + PciIoDevice->PciExpressCapabilityOffset, + sizeof (PCI_CAPABILITY_PCIEXP) / sizeof (UINT8), + &PciIoDevice->PciExpressCapabilityStructure + ); } =20 if (PcdGetBool (PcdAriSupport)) { diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c new file mode 100644 index 0000000..3980a8e --- /dev/null +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c @@ -0,0 +1,891 @@ +/** @file + PCI standard feature support functions implementation for PCI Bus module= .. + +Copyright (c) 2020, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PciBus.h" +#include "PciFeatureSupport.h" + +/** + Hold the current instance of Root Bridge IO protocol Handle +**/ +EFI_HANDLE mRootBridgeHandle; + +/** + A gobal pointer to BRIDGE_DEVICE_NODE buffer to track all the primary ph= ysical + PCI Root Ports (PCI Controllers) for a given PCI Root Bridge instance wh= ile + enumerating to configure the PCI features +**/ +LIST_ENTRY mRootBridgeDeviceList; + +/** + global list to indicate the supported PCI Express features of this driver= , it + is expected to be overridden based on the platform request +**/ +EFI_PCI_EXPRESS_PLATFORM_POLICY mPciExpressPlatformPolicy =3D { + // + // support for PCI Express feature - Max. Payload Size + // + FALSE, + // + // support for PCI Express feature - Max. Read Request Size + // + FALSE, + // + // support for PCI Express feature - Extended Tag + // + FALSE, + // + // support for PCI Express feature - Relax Order + // + FALSE, + // + // support for PCI Express feature - No-Snoop + // + FALSE, + // + // support for PCI Express feature - ASPM state + // + FALSE, + // + // support for PCI Express feature - Common Clock Configuration + // + FALSE, + // + // support for PCI Express feature - Extended Sync + // + FALSE, + // + // support for PCI Express feature - Atomic Op + // + FALSE, + // + // support for PCI Express feature - LTR + // + FALSE, + // + // support for PCI Express feature - PTM + // + FALSE, + // + // support for PCI Express feature - Completion Timeout + // + FALSE, + // + // support for PCI Express feature - Clock Power Management + // + FALSE, + // + // support for PCI Express feature - L1 PM Substates + // + FALSE +}; + +// +// indicates the driver has completed query to platform on the list of sup= ported +// PCI features to be configured +// +BOOLEAN mPciExpressGetPlatformPolicyComplete =3D FALSE; + +// +// PCI Express feature initialization phase handle routines +// +PCI_EXPRESS_FEATURE_INITIALIZATION_POINT mPciExpressFeatureInitialization= List[] =3D { + // + // vacant entry, shall be replaced with actual entry when the PCI Expr= ess + // feature are added. + // + { 0, 0, NULL} +}; + +/** + Routine to serially dispatch the designated the PCI Express feature spec= ific + functions defined for each of the configuration phase. The order for eac= h phase + would be based entirely on the table mPciExpressFeatureInitializationLis= t. + + @param PciDevice pointer to PCI_IO_DEVICE to iden= tify device + @param PciExFeatureConfigPhase input configuration phase + @param PciExpressFeatureConfiguration used pointer to void to accomoda= te any PCI + Express feature specific data ty= pe + @retval EFI_STATUS output only from feature specifi= c function + defined in the table mPciExpress= FeatureInitializationList +**/ +EFI_STATUS +DispatchPciExpressInitializationFunctions ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE PciExFeatureConfigPhase, + IN VOID *PciExpressFeatureConfigurat= ion + ) +{ + UINTN idx; + EFI_STATUS Status; + UINT8 *PciExpressPolicy; + + for ( + idx =3D 0, PciExpressPolicy =3D (UINT8*)&mPciExpressPlatformPolicy + ; idx < sizeof (mPciExpressFeatureInitializationList) / sizeof (PCI_= EXPRESS_FEATURE_INITIALIZATION_POINT) + ; idx++ + ){ + if ( + // + // match the configuration phase + // + mPciExpressFeatureInitializationList[idx].PciExpressFeatureConfigu= rationPhase =3D=3D PciExFeatureConfigPhase + // + // check whether the PCI Express features is enabled + // + && PciExpressPolicy[mPciExpressFeatureInitializationList[idx].PciE= xpressFeatureId] =3D=3D TRUE + ) { + Status =3D mPciExpressFeatureInitializationList[idx].PciExpressFeat= ureConfigurationRoutine ( + PciDevice, + PciExpressFeat= ureConfiguration + ); + } + } + return Status; +} + +/** + Main routine to indicate platform selection of any of the other PCI feat= ures + to be configured by this driver + + @retval TRUE platform has selected the other PCI features to be confi= gured + FALSE platform has not selected any of the other PCI features +**/ +BOOLEAN +CheckPciExpressFeatureList ( + ) +{ + UINTN length; + UINT8 *list; + + for ( + length =3D 0, list =3D (UINT8*)&mPciExpressPlatformPolicy + ; length < sizeof (EFI_PCI_EXPRESS_PLATFORM_POLICY) + ; length++ + ) { + if (list[length]) { + return TRUE; + } + } + return FALSE; +} + +/** + helper routine to wipe out the global PCI Express feature list +**/ +VOID +NegatePciExpressFeatureList ( + ) +{ + UINTN length; + UINT8 *list; + + for ( + length =3D 0, list =3D (UINT8*)&mPciExpressPlatformPolicy + ; length < sizeof (EFI_PCI_EXPRESS_PLATFORM_POLICY) + ; length++ + ) { + if (list[length]) { + list[length] =3D FALSE; + } + } +} + +/** + Main routine to indicate whether the PCI Express feature initialization = is + required or not + + @retval TRUE PCI Express feature initialization required + FALSE PCI Express feature not required +**/ +BOOLEAN +IsPciExpressFeatureConfigurationRequired ( + ) +{ + EFI_STATUS Status; + + if (mPciExpressGetPlatformPolicyComplete) { + return CheckPciExpressFeatureList (); + } + // + // initialize the PCI Express feature data members + // + InitializeListHead (&mRootBridgeDeviceList); + // + // check the platform to configure the PCI Express features + // + mPciExpressGetPlatformPolicyComplete =3D TRUE; + + Status =3D PciExpressPlatformGetPolicy (); + if (EFI_ERROR (Status)) { + // + // fail to obtain the PCI Express feature configuration from platform, + // negate the list to avoid any unwanted configuration + // + NegatePciExpressFeatureList (); + return FALSE; + } + // + // PCI Express feature configuration list is ready from platform + // + return TRUE; +} + + +/** + Indicates whether the set of PCI Express features selected by platform r= equires + extended setup, that has additional resources that would be allocated to= align + all the devices in the PCI tree, and free the resources later. + + @retval TRUE PCI Express feature requires extended setup + FALSE PCI Express feature does not require extended setup +**/ +BOOLEAN +IsPciExpressFeatureExtendedSetupRequired ( + ) +{ + UINTN idx; + UINT8 *PciExpressPolicy; + // + // return TRUE only for those features which are required to be aligned = with + // common values among all the devices in the PCI tree + // + for ( + idx =3D 0, PciExpressPolicy =3D (UINT8*)&mPciExpressPlatformPolicy + ; idx < sizeof (mPciExpressFeatureInitializationList) / sizeof (PCI_= EXPRESS_FEATURE_INITIALIZATION_POINT) + ; idx++ + ){ + if ( + // + // match the configuration phase to extended setup phase + // + mPciExpressFeatureInitializationList[idx].PciExpressFeatureConfigu= rationPhase =3D=3D PciExpressFeatureEntendedSetupPhase + // + // check whether the PCI Express features is enabled + // + && PciExpressPolicy[mPciExpressFeatureInitializationList[idx].PciE= xpressFeatureId] =3D=3D TRUE + ) { + return TRUE; + } + } + + return FALSE; +} + +/** + Helper routine to determine the existence of previously enumerated PCI de= vice + + @retval TRUE PCI device exist + FALSE does not exist +**/ +BOOLEAN +DeviceExist ( + PCI_IO_DEVICE *PciDevice + ) +{ + EFI_PCI_IO_PROTOCOL *PciIoProtocol =3D &PciDevice->PciIo; + UINT16 VendorId =3D 0xFFFF; + + PciIoProtocol->Pci.Read ( + PciIoProtocol, + EfiPciIoWidthUint16, + PCI_VENDOR_ID_OFFSET, + 1, + &VendorId + ); + if (VendorId =3D=3D 0 || VendorId =3D=3D 0xFFFF) { + return FALSE; + } else { + return TRUE; + } +} + +/** + Free up memory alloted for the primary physical PCI Root ports of the PC= I Root + Bridge instance. Free up all the nodes of type BRIDGE_DEVICE_NODE. +**/ +VOID +DestroyRootBridgeDeviceNodes () +{ + LIST_ENTRY *Link; + BRIDGE_DEVICE_NODE *Temp; + + Link =3D mRootBridgeDeviceList.ForwardLink; + while (Link !=3D NULL && Link !=3D &mRootBridgeDeviceList) { + Temp =3D ROOT_BRIDGE_DEVICE_NODE_FROM_LINK (Link); + Link =3D RemoveEntryList (Link); + FreePool (Temp->PciExFeaturesConfigurationTable); + FreePool (Temp); + } +} + +/** + Main routine to determine the child PCI devices of a PCI bridge device + and group them under a common internal PCI features Configuration table. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciFeaturesConfigTable A pointer to a pointer to the + PCI_EXPRESS_FEATURES_CONFIGURATI= ON_TABLE. + Returns NULL in case of RCiEP or= the PCI + device does match with any of th= e physical + Root ports, or it does not belon= g to any + Root port's PCI bus range (not a= child) + + @retval EFI_SUCCESS able to determine the PCI feature + configuration table. For RCiEP s= ince + since it is not prepared. + EFI_DEVICE_ERROR the PCI device has invalid EFI d= evice + path +**/ +EFI_STATUS +GetPciExpressFeaturesConfigurationTable ( + IN PCI_IO_DEVICE *PciDevice, + OUT PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE **PciFeaturesConfigTable + ) +{ + LIST_ENTRY *Link; + BRIDGE_DEVICE_NODE *Temp; + BOOLEAN NodeMatch; + EFI_DEVICE_PATH_PROTOCOL *RootPortPath; + EFI_DEVICE_PATH_PROTOCOL *PciDevicePath; + + if (IsListEmpty (&mRootBridgeDeviceList)) { + // + // no populated PCI primary root ports to parse and match the PCI feat= ures + // configuration table + // + *PciFeaturesConfigTable =3D NULL; + return EFI_SUCCESS; + } + + // + // The PCI features configuration table is not built for RCiEP, return N= ULL + // + if (PciDevice->PciExpressCapabilityStructure.Capability.Bits.DevicePortT= ype =3D=3D \ + PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT) { + *PciFeaturesConfigTable =3D NULL; + return EFI_SUCCESS; + } + + if (IsDevicePathEnd (PciDevice->DevicePath)){ + // + // the given PCI device does not have a valid device path + // + *PciFeaturesConfigTable =3D NULL; + return EFI_DEVICE_ERROR; + } + + + Link =3D mRootBridgeDeviceList.ForwardLink; + do { + Temp =3D ROOT_BRIDGE_DEVICE_NODE_FROM_LINK (Link); + RootPortPath =3D Temp->RootBridgeDevicePath; + PciDevicePath =3D PciDevice->DevicePath; + NodeMatch =3D 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 gi= ven PCI + // device belongs to that PCI tree from the root port + // + if (IsDevicePathEnd (RootPortPath)) { + // + // critical error as no device path available in root + // + *PciFeaturesConfigTable =3D NULL; + return EFI_DEVICE_ERROR; + } + + if (EfiCompareDevicePath (RootPortPath, PciDevicePath)) { + // + // the given PCI device is the primary root port itself + // + *PciFeaturesConfigTable =3D Temp->PciExFeaturesConfigurationTable; + return EFI_SUCCESS; + } + // + // check this PCI device belongs to the primary root port of the root = bridge + // any child PCI device will have the same initial device path nodes = as + // its parent root port + // + while (!IsDevicePathEnd (RootPortPath)){ + + if (DevicePathNodeLength (RootPortPath) !=3D DevicePathNodeLength (P= ciDevicePath)) { + // + // break to check the next primary root port nodes as does not mat= ch + // + NodeMatch =3D FALSE; + break; + } + if (CompareMem (RootPortPath, PciDevicePath, DevicePathNodeLength (R= ootPortPath)) !=3D 0) { + // + // node does not match, break to check next node + // + NodeMatch =3D FALSE; + break; + } + NodeMatch =3D TRUE; + // + // advance to next node + // + RootPortPath =3D NextDevicePathNode (RootPortPath); + PciDevicePath =3D NextDevicePathNode (PciDevicePath); + } + + if (NodeMatch =3D=3D TRUE) { + // + // device belongs to primary root port, return its PCI feature confi= guration + // table + // + *PciFeaturesConfigTable =3D Temp->PciExFeaturesConfigurationTable; + return EFI_SUCCESS; + } + + // + // advance to next Root port node + // + Link =3D Link->ForwardLink; + } while (Link !=3D &mRootBridgeDeviceList && Link !=3D NULL); + // + // the PCI device must be RCiEP, does not belong to any primary root port + // + *PciFeaturesConfigTable =3D NULL; + return EFI_SUCCESS; +} + +/** + helper routine to dump the PCIe Device Port Type +**/ +VOID +DumpDevicePortType ( + IN UINT8 DevicePortType + ) +{ + switch (DevicePortType){ + case PCIE_DEVICE_PORT_TYPE_PCIE_ENDPOINT: + DEBUG (( DEBUG_INFO, "PCIe endpoint found\n")); + break; + case PCIE_DEVICE_PORT_TYPE_LEGACY_PCIE_ENDPOINT: + DEBUG (( DEBUG_INFO, "legacy PCI endpoint found\n")); + break; + case PCIE_DEVICE_PORT_TYPE_ROOT_PORT: + DEBUG (( DEBUG_INFO, "PCIe Root Port found\n")); + break; + case PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT: + DEBUG (( DEBUG_INFO, "PCI switch upstream port found\n")); + break; + case PCIE_DEVICE_PORT_TYPE_DOWNSTREAM_PORT: + DEBUG (( DEBUG_INFO, "PCI switch downstream port found\n")); + break; + case PCIE_DEVICE_PORT_TYPE_PCIE_TO_PCI_BRIDGE: + DEBUG (( DEBUG_INFO, "PCIe-PCI bridge found\n")); + break; + case PCIE_DEVICE_PORT_TYPE_PCI_TO_PCIE_BRIDGE: + DEBUG (( DEBUG_INFO, "PCI-PCIe bridge found\n")); + break; + case PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_INTEGRATED_ENDPOINT: + DEBUG (( DEBUG_INFO, "RCiEP found\n")); + break; + case PCIE_DEVICE_PORT_TYPE_ROOT_COMPLEX_EVENT_COLLECTOR: + DEBUG (( DEBUG_INFO, "RC Event Collector found\n")); + break; + } +} + +/** + Setup each PCI device as per the pltaform's device-specific policy, in = accordance + with PCI Express Base specification. + + @param RootBridge A pointer to the PCI_IO_DEVICE. + + @retval EFI_SUCCESS processing each PCI feature as per policy = defined + was successful. + **/ +EFI_STATUS +SetupDevicePciExpressFeatures ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE PciConfigPhase + ) +{ + EFI_STATUS Status; + PCI_REG_PCIE_CAPABILITY PcieCap; + PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExpressFeaturesConfigTable; + + PciExpressFeaturesConfigTable =3D NULL; + Status =3D GetPciExpressFeaturesConfigurationTable (PciDevice, &PciExpre= ssFeaturesConfigTable); + + if (PciConfigPhase =3D=3D PciExpressFeatureSetupPhase) { + DEBUG_CODE ( + if (EFI_ERROR( Status)) { + DEBUG (( + DEBUG_WARN, + "[Cfg group: 0 {error in dev path}]" + )); + } else if (PciExpressFeaturesConfigTable =3D=3D NULL) { + DEBUG (( + DEBUG_INFO, + "[Cfg group: 0]" + )); + } else { + DEBUG (( + DEBUG_INFO, + "[Cfg group: %d]", + PciExpressFeaturesConfigTable->ID + )); + } + PcieCap.Uint16 =3D PciDevice->PciExpressCapabilityStructure.Capabili= ty.Uint16; + DumpDevicePortType ((UINT8)PcieCap.Bits.DevicePortType); + ); + + // + // get the device-specific platform policy for the PCI Express features + // + Status =3D PciExpressPlatformGetDevicePolicy (PciDevice); + if (EFI_ERROR(Status)) { + DEBUG (( + DEBUG_ERROR, + "Error in obtaining PCI device policy!!!\n" + )); + } + } + + DEBUG ((DEBUG_INFO, "[")); + + Status =3D DispatchPciExpressInitializationFunctions ( + PciDevice, + PciConfigPhase, + PciExpressFeaturesConfigTable + ); + + DEBUG ((DEBUG_INFO, "]\n")); + return Status; +} + +/** + Create and append a node of type BRIDGE_DEVICE_NODE in the list for the = primary + Root Port so that all its child PCI devices can be identified against th= e PCI + features configuration table group ID, of type PCI_EXPRESS_FEATURES_CONF= IGURATION_TABLE. + + @param BridgePort A pointer to the PCI_IO_DEVICE + @param PortNumber A UINTN value to identify the PCI feature configura= tion + table group + + @retval EFI_SUCCESS success in adding a node of BRIDGE_DEVICE_= NODE + to the list + EFI_OUT_OF_RESOURCES unable to get memory for creating the node +**/ +EFI_STATUS +CreatePciRootBridgeDeviceNode ( + IN PCI_IO_DEVICE *BridgePort, + IN UINTN PortNumber + ) +{ + BRIDGE_DEVICE_NODE *RootBridgeNode =3D NULL; + PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciConfigTable =3D NULL; + + RootBridgeNode =3D AllocateZeroPool (sizeof (BRIDGE_DEVICE_NODE)); + if (RootBridgeNode =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + RootBridgeNode->Signature =3D PCI_ROOT_BRIDGE_DEVICE= _SIGNATURE; + RootBridgeNode->RootBridgeDevicePath =3D BridgePort->DevicePath; + PciConfigTable =3D AllocateZeroPool ( + sizeof (PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE) + ); + if (PciConfigTable) { + PciConfigTable->ID =3D PortNumber; + } + + RootBridgeNode->PciExFeaturesConfigurationTable =3D PciConfigTable; + + InsertTailList (&mRootBridgeDeviceList, &RootBridgeNode->NextRootBridgeD= evice); + + if (PciConfigTable =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + return EFI_SUCCESS; +} + +/** + Scan all the nodes of the RootBridge to identify and create a separate l= ist + of all primary physical PCI root ports and link each with its own instan= ce of + the PCI Feature Configuration Table. + + @param RootBridge A pointer to the PCI_IO_DEVICE of the PCI Root Bri= dge + + @retval EFI_OUT_OF_RESOURCES unable to allocate buffer to store PCI fea= ture + configuration table for all the physical P= CI root + ports given + EFI_NOT_FOUND No PCI Bridge device found + EFI_SUCCESS PCI Feature COnfiguration table created fo= r all + the PCI Rooot ports found + EFI_INVALID_PARAMETER invalid parameter passed to the routine wh= ich + creates the PCI controller node for the pr= imary + Root post list +**/ +EFI_STATUS +CreatePciRootBridgeDeviceList ( + IN PCI_IO_DEVICE *RootBridge + ) +{ + EFI_STATUS Status =3D EFI_NOT_FOUND; + LIST_ENTRY *Link; + PCI_IO_DEVICE *Device; + UINTN BridgeDeviceCount; + + BridgeDeviceCount =3D 0; + for ( Link =3D RootBridge->ChildList.ForwardLink + ; Link !=3D &RootBridge->ChildList + ; Link =3D Link->ForwardLink + ) { + Device =3D PCI_IO_DEVICE_FROM_LINK (Link); + if (!DeviceExist (Device)) { + continue; + } + if (IS_PCI_BRIDGE (&Device->Pci)) { + BridgeDeviceCount++; + DEBUG (( + DEBUG_INFO, + "#%d ::Bridge [%02x|%02x|%02x]", + BridgeDeviceCount, Device->BusNumber, Device->DeviceNumber, Device= ->FunctionNumber + )); + // + // create a list of bridge devices if that is connected to any other= device + // + if (!IsListEmpty (&Device->ChildList)) { + DEBUG (( + DEBUG_INFO, + "- has downstream device!\n" + )); + Status =3D CreatePciRootBridgeDeviceNode (Device, BridgeDeviceCoun= t); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "PCI configuration table allocation failure for #%d ::Bridge [= %02x|%02x|%02x]\n", + BridgeDeviceCount, Device->BusNumber, Device->DeviceNumber, De= vice->FunctionNumber + )); + } + } else { + DEBUG (( + DEBUG_INFO, + "- no downstream device!\n" + )); + } + } + } + + return Status; +} + +/** + Initialize the device's PCI Express features, in a staged manner + @param PciDevice A pointer to the PCI_IO_DEVICE. + + @retval EFI_SUCCESS initializing all the nodes of the root bri= dge + instances were successfull. +**/ +EFI_STATUS +InitializeDevicePciExpressFeatures ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE PciConfigPhase + ) +{ + EFI_STATUS Status; + + switch (PciConfigPhase) { + case PciExpressFeatureSetupPhase: + case PciExpressFeatureEntendedSetupPhase: + case PciExpressFeatureProgramPhase: + Status =3D SetupDevicePciExpressFeatures (PciDevice, PciConfigPhase); + break; + case PciExpressFeatureEndPhase: + Status =3D PciExpressPlatformNotifyDeviceState (PciDevice); + break; + } + return Status; +} + +/** + Traverse all the nodes from the root bridge or PCI-PCI bridge instance, = to + configure the PCI Express features as per the PCI Express Base Secificat= ion + by considering its device-specific platform policy, and its device capab= ility, + as applicable. + + @param RootBridge A pointer to the PCI_IO_DEVICE. + + @retval EFI_SUCCESS Traversing all the nodes of the root bridge + instances were successfull. +**/ +EFI_STATUS +InitializePciExpressFeatures ( + IN PCI_IO_DEVICE *RootBridge, + IN PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE PciConfigPhase + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Link; + PCI_IO_DEVICE *Device; + + for ( Link =3D RootBridge->ChildList.ForwardLink + ; Link !=3D &RootBridge->ChildList + ; Link =3D Link->ForwardLink + ) { + Device =3D 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 =3D InitializeDevicePciExpressFeatures ( + Device, + PciConfigPhase + ); + } else { + DEBUG (( + DEBUG_INFO, + "Not a PCIe capable device!\n" + )); + // + // PCI Bridge which does not have PCI Express Capability structure + // cannot process this kind of PCI Bridge device + // + } + + InitializePciExpressFeatures (Device, PciConfigPhase); + } else { + DEBUG (( + DEBUG_INFO, + "::Device [%02x|%02x|%02x] -", + Device->BusNumber, Device->DeviceNumber, Device->FunctionNumber + )); + if (Device->IsPciExp) { + Status =3D InitializeDevicePciExpressFeatures ( + Device, + PciConfigPhase + ); + } else { + DEBUG (( + DEBUG_INFO, + "Not a PCIe capable device!\n" + )); + // + // PCI Device which does not have PCI Express Capability structure + // cannot process this kind of PCI device + // + } + } + } + + return EFI_SUCCESS; +} + +/** + Enumerate all the nodes of the specified root bridge or PCI-PCI Bridge, = to + configure the other PCI features. + + @param RootBridge A pointer to the PCI_IO_DEVICE. + + @retval EFI_SUCCESS The other PCI features configuration durin= g enumeration + of all the nodes of the PCI root bridge in= stance were + programmed in PCI-compliance pattern along= with the + device-specific policy, as applicable. + @retval EFI_UNSUPPORTED One of the override operation maong the no= des of + the PCI hierarchy resulted in a incompatib= le address + range. + @retval EFI_INVALID_PARAMETER The override operation is performed with i= nvalid input + parameters. +**/ +EFI_STATUS +EnumeratePciExpressFeatures ( + IN EFI_HANDLE Controller, + IN PCI_IO_DEVICE *RootBridge + ) +{ + EFI_STATUS Status; + UINTN PciExpressFeatureConfigPhase; + + if (!IsPciExpressFeatureConfigurationRequired ()) { + // + // exit as agreement is not reached with platform to configure the PCI + // Express features + // + return EFI_SUCCESS; + } + mRootBridgeHandle =3D Controller; + + DEBUG_CODE ( + CHAR16 *Str; + Str =3D ConvertDevicePathToText ( + DevicePathFromHandle (RootBridge->Handle), + FALSE, + FALSE + ); + DEBUG (( + DEBUG_INFO, + "Enumerating PCI features for Root Bridge %s\n", + Str !=3D NULL ? Str : L"" + )); + + if (Str !=3D NULL) { + FreePool (Str); + } + ); + + for ( PciExpressFeatureConfigPhase =3D PciExpressFeaturePreProcessPhase + ; PciExpressFeatureConfigPhase <=3D PciExpressFeatureEndPhase + ; PciExpressFeatureConfigPhase++ + ) { + DEBUG (( + DEBUG_INFO, + "<<********** Phase [%d]**********>>\n", + PciExpressFeatureConfigPhase + )); + if (PciExpressFeatureConfigPhase =3D=3D PciExpressFeaturePreProcessPha= se) { + // + // create a list of root bridge devices (root ports) of the root com= plex + // if extra setup phase required + // + if (IsPciExpressFeatureExtendedSetupRequired ()) { + CreatePciRootBridgeDeviceList (RootBridge); + } + continue; + } + if (PciExpressFeatureConfigPhase =3D=3D PciExpressFeatureEntendedSetup= Phase) { + if (!IsPciExpressFeatureExtendedSetupRequired ()) { + // + // since the PCI Express features require no extra initialization = steps + // skip this phase + // + continue; + } + } + // + // setup the PCI Express features + // + Status =3D InitializePciExpressFeatures (RootBridge, PciExpressFeature= ConfigPhase); + + if (PciExpressFeatureConfigPhase =3D=3D PciExpressFeatureEndPhase) { + // + // clean up the temporary resource nodes created for this root bridge + // + if (IsPciExpressFeatureExtendedSetupRequired ()) { + DestroyRootBridgeDeviceNodes (); + } + } + } + + return Status; +} diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h new file mode 100644 index 0000000..2eff8aa --- /dev/null +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h @@ -0,0 +1,226 @@ +/** @file + PCI standard feature support functions implementation for PCI Bus module= .. + +Copyright (c) 2020, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFI_PCI_FEATURES_SUPPORT_H_ +#define _EFI_PCI_FEATURES_SUPPORT_H_ + +extern EFI_HANDLE mRootBridgeHandle; +extern EFI_PCI_EXPRESS_PLATFORM_POLICY mPciExpressPlatformPol= icy; +// +// defines the data structure to hold the details of the PCI Root port dev= ices +// +typedef struct _BRIDGE_DEVICE_NODE BRIDGE_DEVICE_NODE; + +// +// defines the data structure to hold the configuration data for the other= PCI +// features +// +typedef struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE PCI_EXPRESS_FEAT= URES_CONFIGURATION_TABLE; + +// +// define the data type for the PCI feature policy support +// +typedef struct _PCI_FEATURE_POLICY PCI_FEATURE_POLICY; + +// +// Signature value for the PCI Root Port node +// +#define PCI_ROOT_BRIDGE_DEVICE_SIGNATURE SIGNATURE_32 ('p', = 'c', 'i', 'p') + +// +// Definitions of the PCI Root Port data structure members +// +struct _BRIDGE_DEVICE_NODE { + // + // Signature header + // + UINT32 Signature; + // + // linked list pointers to next node + // + LIST_ENTRY NextRootBridgeDevice; + // + // pointer to PCI_IO_DEVICE of the primary PCI Controller device + // + EFI_DEVICE_PATH_PROTOCOL *RootBridgeDevicePath; + // + // pointer to the corresponding PCI Express feature configuration Table = node + // all the child PCI devices of the controller are aligned based on this= table + // + PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExFeaturesConfigurationTab= le; +}; + +#define ROOT_BRIDGE_DEVICE_NODE_FROM_LINK(a) \ + CR (a, BRIDGE_DEVICE_NODE, NextRootBridgeDevice, PCI_ROOT_BRIDGE_DEVICE_= SIGNATURE) + +// +// Definition of the PCI Feature configuration Table members +// +struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE { + // + // Configuration Table ID + // + UINTN ID; +}; + +// +// Declaration of the internal sub-phases during enumeration to configure = the PCI +// Express features +// +typedef enum { + // + // preprocessing applicable only to few PCI Express features to bind all= devices + // under the common root bridge device (root port), that would be useful= to align + // all devices with a common value. This would be optional phase based o= n the + // type of the PCI Express feature to be programmed based on platform po= licy + // + PciExpressFeaturePreProcessPhase, + + // + // mandatory phase to setup the PCI Express feature to its applicable at= tribute, + // based on its device-specific platform policies, matching with its dev= ice capabilities + // + PciExpressFeatureSetupPhase, + + // + // optional phase primarily to align all devices, specially required whe= n PCI + // switch is present in the hierarchy, applicable to certain few PCI Exp= ress + // features only + // + PciExpressFeatureEntendedSetupPhase, + + // + // mandatory programming phase to complete the configuration of the PCI = Express + // features + // + PciExpressFeatureProgramPhase, + + // + // optional phase to clean up temporary buffers, like those that were pr= epared + // during the preprocessing phase above + // + PciExpressFeatureEndPhase + +}PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE; + +// +// declaration for the data type to harbor the PCI feature policies +// +struct _PCI_FEATURE_POLICY { + // + // if set, it indicates the feature should be enabled + // if clear, it indicates the feature should be disabled + // + UINT8 Act : 1; + // + // this field will be specific to feature, it can be implementation spec= ific + // or it can be reserved and remain unused + // + UINT8 Support : 6; + // + // if set indicates override the feature policy defined by the members a= bove + // if clear it indicates that this feature policy should be ignored comp= letely + // this means the above two members should not be used + // + UINT8 Override : 1; +}; + +// +// Declaration of the PCI Express features unique Id +// +typedef enum { + // + // support for PCI Express feature - Max. Payload Size + // + PciExpressMps, + // + // support for PCI Express feature - Max. Read Request Size + // + PciExpressMrrs, + // + // support for PCI Express feature - Extended Tag + // + PciExpressExtTag, + // + // support for PCI Express feature - Relax Order + // + PciExpressRelaxOrder, + // + // support for PCI Express feature - No-Snoop + // + PciExpressNoSnoop, + // + // support for PCI Express feature - ASPM state + // + PciExpressAspm, + // + // support for PCI Express feature - Common Clock Configuration + // + PciExpressCcc, + // + // support for PCI Express feature - Extended Sync + // + PciExpressExtSync, + // + // support for PCI Express feature - Atomic Op + // + PciExpressAtomicOp, + // + // support for PCI Express feature - LTR + // + PciExpressLtr, + // + // support for PCI Express feature - PTM + // + PciExpressPtm, + // + // support for PCI Express feature - Completion Timeout + // + PciExpressCto, + // + // support for PCI Express feature - Clock Power Management + // + PciExpressCpm, + // + // support for PCI Express feature - L1 PM Substates + // + PciExpressL1PmSubstates + +} PCI_EXPRESS_FEATURE_ID; + +// +// PCI Express feature configuration routine during initialization phases +// +typedef +EFI_STATUS +(*PCI_EXPRESS_FEATURE_CONFIGURATION_ROUTINE) ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExpressFeatureConfigurat= ion + ); + +// +// data type for the PCI Express feature initialization phases +// +typedef struct { + // + // Pci Express feature configuration phase + // + PCI_EXPRESS_FEATURE_CONFIGURATION_PHASE PciExpressFeatureConfiguration= Phase; + // + // PCI Express feature Id + // + PCI_EXPRESS_FEATURE_ID PciExpressFeatureId; + // + // PCI Express feature configuration routine + // + PCI_EXPRESS_FEATURE_CONFIGURATION_ROUTINE PciExpressFeatureConfiguration= Routine; + +}PCI_EXPRESS_FEATURE_INITIALIZATION_POINT; + + +#endif diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c new file mode 100644 index 0000000..31c675d --- /dev/null +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c @@ -0,0 +1,302 @@ +/** @file + This file encapsulate the usage of PCI Platform Protocol + + This file define the necessary hooks used to obtain the platform + level data and policies which could be used in the PCI Enumeration phases + +Copyright (c) 2020, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PciBus.h" + + +EFI_PCI_EXPRESS_PLATFORM_PROTOCOL *mPciExPlatformProtocol; +EFI_PCI_EXPRESS_OVERRIDE_PROTOCOL *mPciExOverrideProtocol; + + +/** + This function retrieves the PCI Express Platform Protocols published by = platform + @retval EFI_STATUS direct return status from the LocateProtocol= () + boot service for the PCI Express Override Pr= otocol + EFI_SUCCESS The PCI Express Platform Protocol is found +**/ +EFI_STATUS +GetPciExpressProtocol ( + ) +{ + EFI_STATUS Status; + + if (mPciExPlatformProtocol) { + // + // the PCI Express Platform Protocol is already initialized + // + return EFI_SUCCESS; + } + if (mPciExOverrideProtocol) { + // + // the PCI Express Override Protocol is already initialized + // + return EFI_SUCCESS; + } + // + // locate the PCI Express Platform Protocol + // + Status =3D gBS->LocateProtocol ( + &gEfiPciExpressPlatformProtocolGuid, + NULL, + (VOID **) &mPciExPlatformProtocol + ); + if (!EFI_ERROR (Status)) { + return Status; + } + // + // If PCI Express Platform protocol doesn't exist, try to get the Pci Ex= press + // Override Protocol. + // + return gBS->LocateProtocol ( + &gEfiPciExpressOverrideProtocolGuid, + NULL, + (VOID **) &mPciExOverrideProtocol + ); +} + +/** + This function indicates that the platform has published the PCI Express = Platform + Protocol (or PCI Express Override Protocol) to indicate that this driver= can + initialize the PCI Express features. + @retval TRUE or FALSE +**/ +BOOLEAN +IsPciExpressProtocolPresent ( + ) +{ + if ( + mPciExPlatformProtocol =3D=3D NULL + && mPciExOverrideProtocol =3D=3D NULL + ) { + return FALSE; + } + return TRUE; +} + + +/** + Generic routine to setup the PCI features as per its predetermined defau= lts. +**/ +VOID +SetupDefaultPciExpressDevicePolicy ( + IN PCI_IO_DEVICE *PciDevice + ) +{ + +} + +/** + initialize the device policy data members +**/ +VOID +InitializeDevicePolicyData ( + IN EFI_PCI_EXPRESS_DEVICE_POLICY *PciExpressDevicePolicy + ) +{ + UINTN length; + UINT8 *PciExpressPolicy; + UINT8 *PciExDevicePolicy; + + + ZeroMem (PciExpressDevicePolicy, sizeof (EFI_PCI_EXPRESS_DEVICE_POLICY)); + + for ( + length =3D 0 + , PciExpressPolicy =3D (UINT8*)&mPciExpressPlatformPolicy + , PciExDevicePolicy =3D (UINT8*)PciExpressDevicePolicy + ; length < sizeof (EFI_PCI_EXPRESS_PLATFORM_POLICY) + ; length++ + ) { + if (!PciExpressPolicy[length]) { + PciExDevicePolicy[length] =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; + } + } +} + +/** + Intermediate routine to either get the PCI device specific platform poli= cies + through the PCI Platform Protocol, or its alias the PCI Override Protoco= l. + + @param PciDevice A pointer to PCI_IO_DEVICE + @param PciPlatformProtocol A pointer to EFI_PCI_EXPRESS_PLATFORM_PROTOC= OL + + @retval EFI_STATUS The direct status from the PCI Platform Prot= ocol + @retval EFI_SUCCESS if on returning predetermined PCI features d= efaults, + for the case when protocol returns as EFI_UN= SUPPORTED + to indicate PCI device exist and it has no p= latform + policy defined. +**/ +EFI_STATUS +GetPciExpressDevicePolicy ( + IN PCI_IO_DEVICE *PciDevice, + IN EFI_PCI_EXPRESS_PLATFORM_PROTOCOL *PciPlatformProtocol + ) +{ + EFI_PCI_EXPRESS_DEVICE_POLICY PciExpressDevicePolicy; + EFI_STATUS Status; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress; + + PciAddress.Bus =3D PciDevice->BusNumber; + PciAddress.Device =3D PciDevice->DeviceNumber; + PciAddress.Function =3D PciDevice->FunctionNumber; + PciAddress.Register =3D 0; + PciAddress.ExtendedRegister =3D 0; + + InitializeDevicePolicyData (&PciExpressDevicePolicy); + Status =3D PciPlatformProtocol->GetDevicePolicy ( + PciPlatformProtocol, + mRootBridgeHandle, + PciAddress, + sizeof (EFI_PCI_EXPRESS_DEVICE_POLICY), + &PciExpressDevicePolicy + ); + if (!EFI_ERROR(Status)) { + // + // platform chipset policies are returned for this PCI device + // + + + DEBUG (( + DEBUG_INFO, + "[device policy: platform]" + )); + return Status; + } else if (Status =3D=3D EFI_UNSUPPORTED) { + // + // platform chipset policies are not provided for this PCI device + // let the enumeration happen as per the PCI standard way + // + SetupDefaultPciExpressDevicePolicy (PciDevice); + DEBUG (( + DEBUG_INFO, + "[device policy: default]" + )); + return EFI_SUCCESS; + } + DEBUG (( + DEBUG_ERROR, + "[device policy: none (error)]" + )); + return Status; +} + +/** + Gets the PCI device-specific platform policy from the PCI Express Platfo= rm Protocol. + If no PCI Platform protocol is published than setup the PCI feature to p= redetermined + 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 p= olicy + defined. Also, on returns when no PCI Platform Pro= tocol + exist. +**/ +EFI_STATUS +PciExpressPlatformGetDevicePolicy ( + IN PCI_IO_DEVICE *PciDevice + ) +{ + if (mPciExPlatformProtocol !=3D NULL) { + return GetPciExpressDevicePolicy (PciDevice, mPciExPlatformProtocol); + } else if (mPciExOverrideProtocol !=3D NULL) { + return GetPciExpressDevicePolicy (PciDevice, mPciExOverrideProtocol); + } else { + // + // no protocol found, platform does not require the PCI Express initia= lization + // + return EFI_UNSUPPORTED; + } +} + +/** + This function gets the platform requirement to initialize the list of PC= I Express + features from the protocol definition supported. + This function should be called after the LocatePciPlatformProtocol. + @retval EFI_SUCCESS return by platform to acknowledge the list= of + PCI Express feature to be configured + (in mPciExpressPlatformPolicy) + EFI_INVALID_PARAMETER platform does not support the protocol arg= uements + passed + EFI_UNSUPPORTED platform did not published the protocol +**/ +EFI_STATUS +PciExpressPlatformGetPolicy ( + ) +{ + EFI_STATUS Status; + + if (mPciExPlatformProtocol) { + Status =3D mPciExPlatformProtocol->GetPolicy ( + mPciExPlatformProtocol, + sizeof (EFI_PCI_EXPRESS_PLATFORM_POL= ICY), + &mPciExpressPlatformPolicy + ); + } else if (mPciExOverrideProtocol) { + Status =3D mPciExOverrideProtocol->GetPolicy ( + mPciExOverrideProtocol, + sizeof (EFI_PCI_EXPRESS_PLATFORM_POL= ICY), + &mPciExpressPlatformPolicy + ); + } else { + // + // no protocol found, platform does not require the PCI Express initia= lization + // + return EFI_UNSUPPORTED; + } + return Status; +} + + +/** + Notifies the platform about the current PCI Express state of the device. + + @param PciDevice A pointer to PCI_IO_DEVICE + @param PciExDeviceConfiguration Pointer to EFI_PCI_EXPRESS_DEVICE_CONF= IGURATION. + Used to pass the current state of devi= ce to + platform. + + @retval EFI_STATUS The direct status from the PCI Express Platfor= m Protocol + @retval EFI_UNSUPPORTED returns when the PCI Express Platform Protocol= or its + alias PCI Express OVerride Protocol is not pre= sent. +**/ +EFI_STATUS +PciExpressPlatformNotifyDeviceState ( + IN PCI_IO_DEVICE *PciDevice + ) +{ + EFI_PCI_EXPRESS_DEVICE_CONFIGURATION PciExDeviceConfiguration; + + + if (mPciExPlatformProtocol !=3D NULL) { + return mPciExPlatformProtocol->NotifyDeviceState ( + mPciExPlatformProtocol, + PciDevice->Handle, + sizeof (EFI_PCI_EXPRESS_DEVICE_CONFIGU= RATION), + &PciExDeviceConfiguration + ); + } else if (mPciExOverrideProtocol !=3D NULL) { + return mPciExOverrideProtocol->NotifyDeviceState ( + mPciExOverrideProtocol, + PciDevice->Handle, + sizeof (EFI_PCI_EXPRESS_DEVICE_CONFIGU= RATION), + &PciExDeviceConfiguration + ); + } else { + // + // unexpected error + // + return EFI_UNSUPPORTED; + } +} + diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h new file mode 100644 index 0000000..4283b81 --- /dev/null +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h @@ -0,0 +1,87 @@ +/** @file + This file encapsulate the usage of PCI Platform Protocol + + This file define the necessary hooks used to obtain the platform + level data and policies which could be used in the PCI Enumeration phases + +Copyright (c) 2020, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#ifndef _EFI_PCI_PLATFORM_SUPPORT_H_ +#define _EFI_PCI_PLATFORM_SUPPORT_H_ + + +/** + This function retrieves the PCI Express Platform Protocols published by = platform + @retval EFI_STATUS direct return status from the LocateProtocol= () + boot service for the PCI Express Override Pr= otocol + EFI_SUCCESS The PCI Express Platform Protocol is found +**/ +EFI_STATUS +GetPciExpressProtocol ( + ); + +/** + This function indicates that the platform has published the PCI Express = Platform + Protocol (or PCI Express Override Protocol) to indicate that this driver= can + initialize the PCI Express features. + @retval TRUE or FALSE +**/ +BOOLEAN +IsPciExpressProtocolPresent ( + ); + +/** + This function gets the platform requirement to initialize the list of PC= I Express + features from the protocol definition supported. + This function should be called after the LocatePciPlatformProtocol. + @retval EFI_SUCCESS return by platform to acknowledge the list= of + PCI Express feature to be configured + (in mPciExpressPlatformPolicy) + EFI_INVALID_PARAMETER platform does not support the protocol arg= uements + passed + EFI_UNSUPPORTED platform did not published the protocol +**/ +EFI_STATUS +PciExpressPlatformGetPolicy ( + ); + +/** + Gets the PCI device-specific platform policy from the PCI Platform Proto= col. + If no PCI Platform protocol is published than setup the PCI feature to p= redetermined + 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 p= olicy + defined. Also, on returns when no PCI Platform Pro= tocol + exist. +**/ +EFI_STATUS +PciExpressPlatformGetDevicePolicy ( + IN PCI_IO_DEVICE *PciDevice + ); + +/** + Notifies the platform about the current PCI Express state of the device. + + @param PciDevice A pointer to PCI_IO_DEVICE + @param PciExDeviceConfiguration Pointer to EFI_PCI_EXPRESS_DEVICE_CONF= IGURATION. + Used to pass the current state of devi= ce to + platform. + + @retval EFI_STATUS The direct status from the PCI Express Platfor= m Protocol + @retval EFI_UNSUPPORTED returns when the PCI Express Platform Protocol= or its + alias PCI Express OVerride Protocol is not pre= sent. +**/ +EFI_STATUS +PciExpressPlatformNotifyDeviceState ( + IN PCI_IO_DEVICE *PciDevice + ); +#endif --=20 2.21.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#54064): https://edk2.groups.io/g/devel/message/54064 Mute This Topic: https://groups.io/mt/71063071/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 19 14:36:52 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+54065+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+54065+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1581105968500147.93310493933723; Fri, 7 Feb 2020 12:06:08 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id RykPYY1788612xjbOJgTU9jA; Fri, 07 Feb 2020 12:06:08 -0800 X-Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by mx.groups.io with SMTP id smtpd.web09.10525.1581105967427505892 for ; Fri, 07 Feb 2020 12:06:07 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Feb 2020 12:06:06 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,414,1574150400"; d="scan'208";a="225644163" X-Received: from unknown (HELO PIDSBABIOS005.gar.corp.intel.com) ([10.223.9.183]) by fmsmga007.fm.intel.com with ESMTP; 07 Feb 2020 12:06:04 -0800 From: "Javeed, Ashraf" To: devel@edk2.groups.io Cc: Jian J Wang , Hao A Wu , Ray Ni Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 02/12] MdeModulePkg/PciBusDxe: Setup PCI Express init phase Date: Sat, 8 Feb 2020 01:34:37 +0530 Message-Id: <20200207200447.10536-3-ashraf.javeed@intel.com> In-Reply-To: <20200207200447.10536-1-ashraf.javeed@intel.com> References: <20200207200447.10536-1-ashraf.javeed@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ashraf.javeed@intel.com X-Gm-Message-State: pfztSfJrPGqN3no3h05hFqD3x1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1581105968; bh=ujF5FwecCA/sTgNICgHL7RaFuYbZmuX/4oxt7I1wiog=; h=Cc:Date:From:Reply-To:Subject:To; b=LSd8UI0CQe4UxM5AvZWxKSE3xhw1+BZQatE0ozqxsjVZLUJyhSH68ReaKTKD0dvMitJ z1WsubiGWwxv3QCK+yvF/VR5lsiONHyFjDEY8aToo+1ABJmXAUoOKH3kFDw8f54NZg+fj ks5lEqcWWm/zY/qMV+sQc7+PHMXE9fZdIC8= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" References:- https://bugzilla.tianocore.org/show_bug.cgi?id=3D1954 https://bugzilla.tianocore.org/show_bug.cgi?id=3D2194 https://bugzilla.tianocore.org/show_bug.cgi?id=3D2313 https://bugzilla.tianocore.org/show_bug.cgi?id=3D2499 https://bugzilla.tianocore.org/show_bug.cgi?id=3D2500 This code change represents the preparation of phase for initializing the PCI Express features at the end of PCI enumeration phase. Signed-off-by: Ashraf Javeed Cc: Jian J Wang Cc: Hao A Wu Cc: Ray Ni --- MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c | 181 +++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------= -------------- MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h | 23 +++++++++++++++++= ++++++ 2 files changed, 169 insertions(+), 35 deletions(-) diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c b/MdeModuleP= kg/Bus/Pci/PciBusDxe/PciDeviceSupport.c index b7832c6..07ee9ba 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c @@ -1,7 +1,7 @@ /** @file Supporting functions implementation for PCI devices management. =20 -Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.
(C) Copyright 2018 Hewlett Packard Enterprise Development LP
SPDX-License-Identifier: BSD-2-Clause-Patent =20 @@ -597,7 +597,7 @@ DeRegisterPciDevice ( } =20 /** - Start to manage the PCI device on the specified root bridge or PCI-PCI B= ridge. + Start the PCI root Ports or PCI-PCI Bridge only. =20 @param Controller The root bridge handle. @param RootBridge A pointer to the PCI_IO_DEVICE. @@ -612,7 +612,82 @@ DeRegisterPciDevice ( =20 **/ EFI_STATUS -StartPciDevicesOnBridge ( +EnablePciBridges ( + IN EFI_HANDLE Controller, + IN PCI_IO_DEVICE *RootBridge + ) + +{ + PCI_IO_DEVICE *PciIoDevice; + EFI_STATUS Status; + LIST_ENTRY *CurrentLink; + UINT64 Supports; + + PciIoDevice =3D NULL; + CurrentLink =3D RootBridge->ChildList.ForwardLink; + + while (CurrentLink !=3D NULL && CurrentLink !=3D &RootBridge->ChildList)= { + + PciIoDevice =3D 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 =3D EnablePciBridges ( + Controller, + PciIoDevice + ); + + PciIoDevice->PciIo.Attributes ( + &(PciIoDevice->PciIo), + EfiPciIoAttributeOperationSupported, + 0, + &Supports + ); + Supports &=3D (UINT64)EFI_PCI_DEVICE_ENABLE; + PciIoDevice->PciIo.Attributes ( + &(PciIoDevice->PciIo), + EfiPciIoAttributeOperationEnable, + Supports, + NULL + ); + + } + + CurrentLink =3D CurrentLink->ForwardLink; + } + + if (PciIoDevice =3D=3D NULL) { + return EFI_NOT_FOUND; + } else { + return EFI_SUCCESS; + } +} + + +/** + Register to manage the PCI device on the specified root bridge or PCI-PC= I Bridge. + + @param Controller The root bridge handle. + @param RootBridge A pointer to the PCI_IO_DEVICE. + @param RemainingDevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL. + @param NumberOfChildren Children number. + @param ChildHandleBuffer A pointer to the child handle buffer. + + @retval EFI_NOT_READY Device is not allocated. + @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge. + @retval EFI_NOT_FOUND Can not find the specific device. + @retval EFI_SUCCESS Success to start Pci devices on bridge. + +**/ +EFI_STATUS +RegisterPciDevicesOnBridge ( IN EFI_HANDLE Controller, IN PCI_IO_DEVICE *RootBridge, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath, @@ -626,7 +701,6 @@ StartPciDevicesOnBridge ( EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath; EFI_STATUS Status; LIST_ENTRY *CurrentLink; - UINT64 Supports; =20 PciIoDevice =3D NULL; CurrentLink =3D RootBridge->ChildList.ForwardLink; @@ -681,7 +755,7 @@ StartPciDevicesOnBridge ( // If it is a PPB // if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) { - Status =3D StartPciDevicesOnBridge ( + Status =3D RegisterPciDevicesOnBridge ( Controller, PciIoDevice, CurrentDevicePath, @@ -689,20 +763,6 @@ StartPciDevicesOnBridge ( ChildHandleBuffer ); =20 - PciIoDevice->PciIo.Attributes ( - &(PciIoDevice->PciIo), - EfiPciIoAttributeOperationSupported, - 0, - &Supports - ); - Supports &=3D (UINT64)EFI_PCI_DEVICE_ENABLE; - PciIoDevice->PciIo.Attributes ( - &(PciIoDevice->PciIo), - EfiPciIoAttributeOperationEnable, - Supports, - NULL - ); - return Status; } else { =20 @@ -733,28 +793,13 @@ StartPciDevicesOnBridge ( } =20 if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) { - Status =3D StartPciDevicesOnBridge ( + Status =3D RegisterPciDevicesOnBridge ( Controller, PciIoDevice, RemainingDevicePath, NumberOfChildren, ChildHandleBuffer ); - - PciIoDevice->PciIo.Attributes ( - &(PciIoDevice->PciIo), - EfiPciIoAttributeOperationSupported, - 0, - &Supports - ); - Supports &=3D (UINT64)EFI_PCI_DEVICE_ENABLE; - PciIoDevice->PciIo.Attributes ( - &(PciIoDevice->PciIo), - EfiPciIoAttributeOperationEnable, - Supports, - NULL - ); - } =20 CurrentLink =3D CurrentLink->ForwardLink; @@ -768,6 +813,72 @@ StartPciDevicesOnBridge ( } } =20 +/** + Start to manage the PCI device on the specified root bridge or PCI-PCI B= ridge. + + @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 =3D RegisterPciDevicesOnBridge ( + Controller, + RootBridge, + RemainingDevicePath, + NumberOfChildren, + ChildHandleBuffer + ); + + if (EFI_ERROR (Status)) { + return Status; + } else { + // + // the late configuration of PCI Express features + // the platform is required to indicate its requirement for the initia= lization + // of PCI Express features by publishing its protocol + // + if ( + gFullEnumeration + && IsPciExpressProtocolPresent () + ) { + + Status =3D EnumeratePciExpressFeatures ( + Controller, + RootBridge + ); + } + // + // finally start those PCI bridge port devices only + // + return EnablePciBridges ( + Controller, + RootBridge + ); + } +} + /** Start to manage all the PCI devices it found previously under the entire host bridge. diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h index 2eff8aa..9b7e51f 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h @@ -223,4 +223,27 @@ typedef struct { }PCI_EXPRESS_FEATURE_INITIALIZATION_POINT; =20 =20 + +/** + 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 durin= g enumeration + of all the nodes of the PCI root bridge in= stance were + programmed in PCI-compliance pattern along= with the + device-specific policy, as applicable. + @retval EFI_UNSUPPORTED One of the override operation maong the no= des of + the PCI hierarchy resulted in a incompatib= le address + range. + @retval EFI_INVALID_PARAMETER The override operation is performed with i= nvalid input + parameters. +**/ +EFI_STATUS +EnumeratePciExpressFeatures ( + IN EFI_HANDLE Controller, + IN PCI_IO_DEVICE *RootBridge + ); + #endif --=20 2.21.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#54065): https://edk2.groups.io/g/devel/message/54065 Mute This Topic: https://groups.io/mt/71063074/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 19 14:36:52 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+54066+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+54066+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1581105973146746.9012089561598; Fri, 7 Feb 2020 12:06:13 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id JWEaYY1788612x7x7eZRKGZC; Fri, 07 Feb 2020 12:06:12 -0800 X-Received: from mga03.intel.com (mga03.intel.com []) by mx.groups.io with SMTP id smtpd.web09.10525.1581105967427505892 for ; Fri, 07 Feb 2020 12:06:12 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Feb 2020 12:06:11 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,414,1574150400"; d="scan'208";a="225644214" X-Received: from unknown (HELO PIDSBABIOS005.gar.corp.intel.com) ([10.223.9.183]) by fmsmga007.fm.intel.com with ESMTP; 07 Feb 2020 12:06:09 -0800 From: "Javeed, Ashraf" To: devel@edk2.groups.io Cc: Jian J Wang , Hao A Wu , Ray Ni Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 03/12] PciBusDxe: New PCI Express feature Max_Payload_Size Date: Sat, 8 Feb 2020 01:34:38 +0530 Message-Id: <20200207200447.10536-4-ashraf.javeed@intel.com> In-Reply-To: <20200207200447.10536-1-ashraf.javeed@intel.com> References: <20200207200447.10536-1-ashraf.javeed@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ashraf.javeed@intel.com X-Gm-Message-State: UFr5vQ7YlraUkDGCqHkU4Equx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1581105972; bh=49ZW5KCVWgNveUeCvK+GKNO6v+fH3mY0HW6ZsanV5gU=; h=Cc:Date:From:Reply-To:Subject:To; b=rCza2lefShQ33QPbACd0inhGh7ENDZEiTNI7eok2CDY+44MHnEtUq99SpK+NaEmQPr7 o0pYuUZMKHQd/r/y0dMnD3zr1Tc0SRJE87QCmX26yG+KXOANX7LLuMVmlqoU0UI0Gz4ar 2Eu2YKqnaN2Nfthz+WQqy7cb7qu4jT2AwJg= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2194 The code changes are made to enable the configuration of new PCI Express feature Max_Payload_Size (MPS), which defines the data packet size for the PCI transactions, as per the PCI Base Specification 4 Revision 1. The code changes are made to calibrate highest common value that is appl- icable to all the child nodes originating from the primary root bridge device instance. This programming of MPS is based on each PCI device's capability, and also its device-specific platform policy obtained using the new PCI Express Platform Protocol interface, defined in the below feature request:- https://bugzilla.tianocore.org/show_bug.cgi?id=3D1954 Signed-off-by: Ashraf Javeed Cc: Jian J Wang Cc: Hao A Wu Cc: Ray Ni --- MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h | 1 + MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf | 2 ++ MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c | 193 ++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h | 55 ++++++++++++++++= +++++++++++++++++++++++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c | 22 ++++++++++++++++= ------ MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h | 5 +++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 80 ++++++++++++++++= ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h | 17 +++++++++++++++++ 8 files changed, 369 insertions(+), 6 deletions(-) diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci= /PciBusDxe/PciBus.h index 225229d..5dc5f61 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h @@ -287,6 +287,7 @@ struct _PCI_IO_DEVICE { // This field is used to support this case. // UINT16 BridgeIoAlignment; + UINT8 SetupMPS; }; =20 #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf b/MdeModulePkg/Bu= s/Pci/PciBusDxe/PciBusDxe.inf index f06b411..e3ad105 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf @@ -61,6 +61,8 @@ PciFeatureSupport.h PciPlatformSupport.c PciPlatformSupport.h + PciExpressFeatures.c + PciExpressFeatures.h =20 [Packages] MdePkg/MdePkg.dec diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c new file mode 100644 index 0000000..6084446 --- /dev/null +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c @@ -0,0 +1,193 @@ +/** @file + PCI standard feature support functions implementation for PCI Bus module= .. + +Copyright (c) 2020, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "PciBus.h" +#include "PciFeatureSupport.h" + +VOID +ReportPciWriteError ( + IN UINT8 Bus, + IN UINT8 Device, + IN UINT8 Function, + IN UINT32 Offset + ) +{ + DEBUG (( + DEBUG_ERROR, + "Unexpected PCI register (%d,%d,%d,0x%x) write error!", + Bus, + Device, + Function, + Offset + )); +} + +/** + Compare and Swap the payload value - between the global variable to maai= ntain + common value among all the devices in the PCIe heirarchy from the root b= ridge + device and all its child devices; with the device-sepcific setup value. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciExpressConfigurationTable pointer to PCI_EXPRESS_FEATURES_CON= FIGURATION_TABLE + + @retval EFI_SUCCESS processing of PCI feature Max_Payl= oad_Size + is successful. +**/ +EFI_STATUS +CasMaxPayloadSize ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExpressConfiguration= Table + ) +{ + UINT8 MpsValue; + + // + // align the MPS of the tree to the HCF with this device + // + if (PciExpressConfigurationTable) { + MpsValue =3D PciExpressConfigurationTable->Max_Payload_Size; + + MpsValue =3D MIN (PciDevice->SetupMPS, MpsValue); + PciDevice->SetupMPS =3D MIN (PciDevice->SetupMPS, MpsValue); + + if (MpsValue !=3D PciExpressConfigurationTable->Max_Payload_Size) { + PciExpressConfigurationTable->Max_Payload_Size =3D MpsValue; + } + } + + DEBUG (( + DEBUG_INFO, + "MPS: %d [DevCap:%d],", + PciDevice->SetupMPS, PciDevice->PciExpressCapabilityStructure.DeviceCa= pability.Bits.MaxPayloadSize + )); + + return EFI_SUCCESS; +} + +/** + The main routine which process the PCI feature Max_Payload_Size as per t= he + device-specific platform policy, as well as in complaince with the PCI B= ase + specification Revision 4, that aligns the value for the entire PCI heira= rchy + starting from its physical PCI Root port / Bridge device. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciExpressConfigurationTable pointer to PCI_EXPRESS_FEATURES_CON= FIGURATION_TABLE + + @retval EFI_SUCCESS processing of PCI feature Max_Payl= oad_Size + is successful. +**/ +EFI_STATUS +SetupMaxPayloadSize ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExpressConfigurationTa= ble + ) +{ + PCI_REG_PCIE_DEVICE_CAPABILITY PciDeviceCap; + UINT8 MpsValue; + + + PciDeviceCap.Uint32 =3D PciDevice->PciExpressCapabilityStructure.DeviceC= apability.Uint32; + + if (PciDevice->SetupMPS =3D=3D EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_AUTO) { + // + // configure this feature as per its PCIe device capabilities + // + MpsValue =3D (UINT8)PciDeviceCap.Bits.MaxPayloadSize; + // + // no change to PCI Root ports without any endpoint device + // + if (IS_PCI_BRIDGE (&PciDevice->Pci) && PciDeviceCap.Bits.MaxPayloadSiz= e) { + if (IsListEmpty (&PciDevice->ChildList)) { + // + // No device on root bridge + // + MpsValue =3D PCIE_MAX_PAYLOAD_SIZE_128B; + } + } + } else { + MpsValue =3D SetDevicePolicyPciExpressMps (PciDevice->SetupMPS); + } + // + // discard device policy override request if greater than PCI device cap= ability + // + PciDevice->SetupMPS =3D MIN ((UINT8)PciDeviceCap.Bits.MaxPayloadSize, Mp= sValue); + + return CasMaxPayloadSize ( + PciDevice, + PciExpressConfigurationTable + ); +} + +/** + Overrides the PCI Device Control register MaxPayloadSize register field;= if + the hardware value is different than the intended value. + + @param PciDevice A pointer to the PCI_IO_DEVICE instance. + + @retval EFI_SUCCESS The data was read from or written to the P= CI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramMaxPayloadSize ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExFeatureConfiguration + ) +{ + PCI_REG_PCIE_DEVICE_CONTROL PcieDev; + UINT32 Offset; + EFI_STATUS Status; + EFI_TPL OldTpl; + + PcieDev.Uint16 =3D 0; + Offset =3D PciDevice->PciExpressCapabilityOffset + + OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl); + Status =3D PciDevice->PciIo.Pci.Read ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &PcieDev.Uint16 + ); + ASSERT (Status =3D=3D EFI_SUCCESS); + + if (PcieDev.Bits.MaxPayloadSize !=3D PciDevice->SetupMPS) { + PcieDev.Bits.MaxPayloadSize =3D PciDevice->SetupMPS; + DEBUG (( DEBUG_INFO, "MPS=3D%d,", PciDevice->SetupMPS)); + + // + // Raise TPL to high level to disable timer interrupt while the write = operation completes + // + OldTpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + + Status =3D PciDevice->PciIo.Pci.Write ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &PcieDev.Uint16 + ); + // + // Restore TPL to its original level + // + gBS->RestoreTPL (OldTpl); + + if (!EFI_ERROR(Status)) { + PciDevice->PciExpressCapabilityStructure.DeviceControl.Uint16 =3D Pc= ieDev.Uint16; + } else { + ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, = PciDevice->FunctionNumber, Offset); + } + } else { + DEBUG (( DEBUG_INFO, "No MPS=3D%d,", PciDevice->SetupMPS)); + } + + return Status; +} + diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h new file mode 100644 index 0000000..460437b --- /dev/null +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h @@ -0,0 +1,55 @@ +/** @file + PCI standard feature support functions implementation for PCI Bus module= .. + +Copyright (c) 2020, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFI_PCI_EXPRESS_FEATURES_H_ +#define _EFI_PCI_EXPRESS_FEATURES_H_ + + +/** + The main routine which process the PCI feature Max_Payload_Size as per t= he + device-specific platform policy, as well as in complaince with the PCI B= ase + specification Revision 4, that aligns the value for the entire PCI heira= rchy + starting from its physical PCI Root port / Bridge device. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciFeaturesConfigurationTable pointer to PCI_EXPRESS_FEATURES_CO= NFIGURATION_TABLE + + @retval EFI_SUCCESS processing of PCI feature Max_Payl= oad_Size + is successful. +**/ +EFI_STATUS +SetupMaxPayloadSize ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciFeaturesConfigurationT= able + ); + +EFI_STATUS +CasMaxPayloadSize ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciFeaturesConfigurationT= able + ); + +/** + Overrides the PCI Device Control register Max_Read_Req_Size register fie= ld; 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 P= CI controller. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramMaxPayloadSize ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExFeatureConfiguration + ); + +#endif diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c index 3980a8e..aae6139 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c @@ -8,6 +8,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent =20 #include "PciBus.h" #include "PciFeatureSupport.h" +#include "PciExpressFeatures.h" =20 /** Hold the current instance of Root Bridge IO protocol Handle @@ -29,7 +30,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY mPciExpressPl= atformPolicy =3D { // // support for PCI Express feature - Max. Payload Size // - FALSE, + TRUE, // // support for PCI Express feature - Max. Read Request Size // @@ -94,11 +95,16 @@ BOOLEAN mPciExpressGetPlatformPolicyComplete =3D FALS= E; // PCI Express feature initialization phase handle routines // PCI_EXPRESS_FEATURE_INITIALIZATION_POINT mPciExpressFeatureInitialization= List[] =3D { - // - // vacant entry, shall be replaced with actual entry when the PCI Expr= ess - // feature are added. - // - { 0, 0, NULL} + + { + PciExpressFeatureSetupPhase, PciExpressMps, SetupMaxPa= yloadSize + }, + { + PciExpressFeatureEntendedSetupPhase, PciExpressMps, CasMaxPayl= oadSize + }, + { + PciExpressFeatureProgramPhase, PciExpressMps, ProgramMax= PayloadSize + } }; =20 /** @@ -597,6 +603,10 @@ CreatePciRootBridgeDeviceNode ( ); if (PciConfigTable) { PciConfigTable->ID =3D PortNumber; + // + // start by assuming 4096B as the default value for the Max. Payload S= ize + // + PciConfigTable->Max_Payload_Size =3D PCIE_MAX_PAYLOAD_SIZE_= 4096B; } =20 RootBridgeNode->PciExFeaturesConfigurationTable =3D PciConfigTable; diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h index 9b7e51f..4ecbefc 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h @@ -66,6 +66,11 @@ struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE { // Configuration Table ID // UINTN ID; + // + // to configure the PCI feature Maximum payload size to maintain the dat= a packet + // size among all the PCI devices in the PCI hierarchy + // + UINT8 Max_Payload_Size; }; =20 // diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c index 31c675d..3e9d4c5 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c @@ -81,6 +81,39 @@ IsPciExpressProtocolPresent ( return TRUE; } =20 +/** + Routine to translate the given device-specific platform policy from type + EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE to HW-specific value, as per PCI Base S= pecification + Revision 4.0; for the PCI feature Max_Payload_Size. + + @param MPS Input device-specific policy should be in terms of type + EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE + + @retval Range values for the Max_Payload_Size as defined in the = PCI + Base Specification 4.0 +**/ +UINT8 +SetDevicePolicyPciExpressMps ( + IN UINT8 MPS +) +{ + switch (MPS) { + case EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_128B: + return PCIE_MAX_PAYLOAD_SIZE_128B; + case EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_256B: + return PCIE_MAX_PAYLOAD_SIZE_256B; + case EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_512B: + return PCIE_MAX_PAYLOAD_SIZE_512B; + case EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_1024B: + return PCIE_MAX_PAYLOAD_SIZE_1024B; + case EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_2048B: + return PCIE_MAX_PAYLOAD_SIZE_2048B; + case EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_4096B: + return PCIE_MAX_PAYLOAD_SIZE_4096B; + default: + return PCIE_MAX_PAYLOAD_SIZE_128B; + } +} =20 /** Generic routine to setup the PCI features as per its predetermined defau= lts. @@ -91,6 +124,12 @@ SetupDefaultPciExpressDevicePolicy ( ) { =20 + if (mPciExpressPlatformPolicy.Mps) { + PciDevice->SetupMPS =3D EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_AUTO; + } else { + PciDevice->SetupMPS =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; + } + } =20 /** @@ -163,6 +202,15 @@ GetPciExpressDevicePolicy ( // platform chipset policies are returned for this PCI device // =20 + // + // set device specific policy for the Max_Payload_Size + // + if (mPciExpressPlatformPolicy.Mps) { + PciDevice->SetupMPS =3D PciExpressDevicePolicy.DeviceCtlMPS; + } else { + PciDevice->SetupMPS =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; + } + =20 DEBUG (( DEBUG_INFO, @@ -257,6 +305,28 @@ PciExpressPlatformGetPolicy ( return Status; } =20 +EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE +GetPciExpressMps ( + IN UINT8 Mps + ) +{ + switch (Mps) { + case PCIE_MAX_PAYLOAD_SIZE_128B: + return EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_128B; + case PCIE_MAX_PAYLOAD_SIZE_256B: + return EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_256B; + case PCIE_MAX_PAYLOAD_SIZE_512B: + return EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_512B; + case PCIE_MAX_PAYLOAD_SIZE_1024B: + return EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_1024B; + case PCIE_MAX_PAYLOAD_SIZE_2048B: + return EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_2048B; + case PCIE_MAX_PAYLOAD_SIZE_4096B: + return EFI_PCI_EXPRESS_MAX_PAYLOAD_SIZE_4096B; + } + return EFI_PCI_EXPRESS_NOT_APPLICABLE; +} + =20 /** Notifies the platform about the current PCI Express state of the device. @@ -277,6 +347,16 @@ PciExpressPlatformNotifyDeviceState ( { EFI_PCI_EXPRESS_DEVICE_CONFIGURATION PciExDeviceConfiguration; =20 + // + // get the device-specific state for the PCIe Max_Payload_Size feature + // + if (mPciExpressPlatformPolicy.Mps) { + PciExDeviceConfiguration.DeviceCtlMPS =3D GetPciExpressMps ( + (UINT8)PciDevice->PciExpress= CapabilityStructure.DeviceControl.Bits.MaxPayloadSize + ); + } else { + PciExDeviceConfiguration.DeviceCtlMPS =3D EFI_PCI_EXPRESS_NOT_APPLICAB= LE; + } =20 if (mPciExPlatformProtocol !=3D NULL) { return mPciExPlatformProtocol->NotifyDeviceState ( diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h index 4283b81..5ae6386 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h @@ -84,4 +84,21 @@ EFI_STATUS PciExpressPlatformNotifyDeviceState ( IN PCI_IO_DEVICE *PciDevice ); + +/** + Routine to translate the given device-specific platform policy from type + EFI_PCI_CONF_MAX_PAYLOAD_SIZE to HW-specific value, as per PCI Base Spec= ification + Revision 4.0; for the PCI feature Max_Payload_Size. + + @param MPS Input device-specific policy should be in terms of type + EFI_PCI_CONF_MAX_PAYLOAD_SIZE + + @retval Range values for the Max_Payload_Size as defined in the = PCI + Base Specification 4.0 +**/ +UINT8 +SetDevicePolicyPciExpressMps ( + IN UINT8 MPS +); + #endif --=20 2.21.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#54066): https://edk2.groups.io/g/devel/message/54066 Mute This Topic: https://groups.io/mt/71063076/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 19 14:36:52 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+54067+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+54067+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1581105979429937.361203480974; Fri, 7 Feb 2020 12:06:19 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id JR2WYY1788612xAwpPCmiEQH; Fri, 07 Feb 2020 12:06:19 -0800 X-Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by mx.groups.io with SMTP id smtpd.web09.10529.1581105978095314348 for ; Fri, 07 Feb 2020 12:06:18 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Feb 2020 12:06:17 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,414,1574150400"; d="scan'208";a="225644233" X-Received: from unknown (HELO PIDSBABIOS005.gar.corp.intel.com) ([10.223.9.183]) by fmsmga007.fm.intel.com with ESMTP; 07 Feb 2020 12:06:15 -0800 From: "Javeed, Ashraf" To: devel@edk2.groups.io Cc: Jian J Wang , Hao A Wu , Ray Ni Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 04/12] PciBusDxe: New PCI Express feature Max_Read_Req_Size Date: Sat, 8 Feb 2020 01:34:39 +0530 Message-Id: <20200207200447.10536-5-ashraf.javeed@intel.com> In-Reply-To: <20200207200447.10536-1-ashraf.javeed@intel.com> References: <20200207200447.10536-1-ashraf.javeed@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ashraf.javeed@intel.com X-Gm-Message-State: PyHAW292GiAsuUsvvgQoq49Sx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1581105979; bh=+az9dXPVQKzwpwcoua9AlccBh9BWzpW4V8QFyX8aFt4=; h=Cc:Date:From:Reply-To:Subject:To; b=SnaFv8HcrlxhP09SXOly5UQinTKI9e93OVQYoSqBOLIQvkStZUB51dF90lHdAZuNe3Y CAUoFU+ksvP6n+NDDjceJO+e7WtjZylI8EEVm3u2iGyDJLHm8HFAOLURhfKqAwFP9LJeq At0equJkuSPv9AavGsdvgMrgmwzTJ2uyfO4= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2194 The code changes are made to enable the configuration of PCI Express feature Max_Read_Req_Size (MRRS), which defines the memory read request size for the PCI transactions, as per the PCI Base Specification 4 Revision 1. The code changes are made to configure a common value that is applicable to all the child nodes originating from the root bridge device instance, based on following 3 criteria:- (1) if platform defines MRRS device policy for any one PCI device in the tree than align all the devices in the PCI tree to that same value (2) if platform does not provide device policy for any of the devices in the PCI tree than setup the MRRS value equivalent to MPS value for all PCI devices to meet the criteria for the isochronous traffic (3) if platform does not provide device policy for any of the devices and it has not selected the MPS to be configured either; than the config- uration of the MRRS is performed based on highest common value of the MPS advertized in the PCI device capability registers of the devices This programming of MRRS gets the device-specific platform policy using the new PCI Express Platform Protocol interface, defined in the below feature request:- https://bugzilla.tianocore.org/show_bug.cgi?id=3D1954 Signed-off-by: Ashraf Javeed Cc: Jian J Wang Cc: Hao A Wu Cc: Ray Ni --- MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h | 1 + MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c | 190 ++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h | 45 ++++++++++++++++= +++++++++++++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c | 20 ++++++++++++++++= +++- MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h | 9 +++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 81 ++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h | 15 +++++++++++++++ 7 files changed, 360 insertions(+), 1 deletion(-) diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci= /PciBusDxe/PciBus.h index 5dc5f61..77b44c0 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h @@ -288,6 +288,7 @@ struct _PCI_IO_DEVICE { // UINT16 BridgeIoAlignment; UINT8 SetupMPS; + UINT8 SetupMRRS; }; =20 #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c index 6084446..2810158 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c @@ -191,3 +191,193 @@ ProgramMaxPayloadSize ( return Status; } =20 +EFI_STATUS +ConditionalCasMaxReadReqSize ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExpressConfigurationTa= ble + ) +{ + // + // 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 a= lign + // all the devices in the PCI tree. + // second, if user override is not define for this PCI tree than setup t= he MRRS + // based on MPS value of the tree to meet the criteria for the isochrono= us + // traffic. + // third, if no user override, or platform firmware policy has not selec= ted + // this PCI bus driver to configure the MPS; than configure the MRRS to a + // highest common value of PCI device capability for the MPS found among= all + // the PCI devices in this tree + // + if (PciExpressConfigurationTable) { + if (PciExpressConfigurationTable->Lock_Max_Read_Request_Size) { + PciDevice->SetupMRRS =3D PciExpressConfigurationTable->Max_Read_Requ= est_Size; + } else { + if (mPciExpressPlatformPolicy.Mps) { + PciDevice->SetupMRRS =3D PciDevice->SetupMPS; + } else { + PciDevice->SetupMRRS =3D MIN ( + PciDevice->SetupMRRS, + PciExpressConfigurationTable->Max_Read_Req= uest_Size + ); + } + PciExpressConfigurationTable->Max_Read_Request_Size =3D PciDevice->S= etupMRRS; + } + } + DEBUG (( DEBUG_INFO, "MRRS: %d,", PciDevice->SetupMRRS)); + + return EFI_SUCCESS; +} + +/** + The main routine which process the PCI feature Max_Read_Req_Size as per = the + device-specific platform policy, as well as in complaince with the PCI B= ase + specification Revision 4, that aligns the value for the entire PCI heira= rchy + starting from its physical PCI Root port / Bridge device. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciExpressConfigurationTable pointer to PCI_EXPRESS_FEATURES_CON= FIGURATION_TABLE + + @retval EFI_SUCCESS processing of PCI feature Max_Read= _Req_Size + is successful. +**/ +EFI_STATUS +SetupMaxReadReqSize ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExpressConfigurationTa= ble + ) +{ + PCI_REG_PCIE_DEVICE_CAPABILITY PciDeviceCap; + UINT8 MrrsValue; + + PciDeviceCap.Uint32 =3D PciDevice->PciExpressCapabilityStructure.DeviceC= apability.Uint32; + + if (PciDevice->SetupMRRS =3D=3D EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_AUTO) { + // + // The maximum read request size is not the data packet size of the TL= P, + // but the memory read request size, and set to the function as a requ= estor + // to not exceed this limit. + // However, for the PCI device capable of isochronous traffic; this me= mory read + // request size should not extend beyond the Max_Payload_Size. Thus, i= n case if + // device policy return by platform indicates to set as per device cap= ability + // than set as per Max_Payload_Size configuration value + // + if (mPciExpressPlatformPolicy.Mps) { + MrrsValue =3D 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_Payl= oad_Size + // in this PCI hierarchy; thus making this an implementation specifi= c feature + // which the platform should avoid. For better results, the platform= should + // make both the Max_Payload_Size & Max_Read_Request_Size to be conf= igured + // by this driver + // + MrrsValue =3D (UINT8)PciDeviceCap.Bits.MaxPayloadSize; + } + } else { + // + // override as per platform based device policy + // + MrrsValue =3D SetDevicePolicyPciExpressMrrs (PciDevice->SetupMRRS); + // + // align this device's Max_Read_Request_Size value to the entire PCI t= ree + // + if (PciExpressConfigurationTable) { + if (!PciExpressConfigurationTable->Lock_Max_Read_Request_Size) { + PciExpressConfigurationTable->Lock_Max_Read_Request_Size =3D TRUE; + PciExpressConfigurationTable->Max_Read_Request_Size =3D 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 s= et + // across entire PCI tree nodes + // + MrrsValue =3D MIN ( + MrrsValue, + PciExpressConfigurationTable->Max_Read_Request_Size + ); + PciExpressConfigurationTable->Max_Read_Request_Size =3D MrrsValue; + } + } + } + // + // align this device's Max_Read_Request_Size to derived configuration va= lue + // + PciDevice->SetupMRRS =3D MrrsValue; + + return ConditionalCasMaxReadReqSize ( + PciDevice, + PciExpressConfigurationTable + ); +} + + +/** + Overrides the PCI Device Control register Max_Read_Req_Size register fie= ld; 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 P= CI controller. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramMaxReadReqSize ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExFeatureConfiguration + ) +{ + PCI_REG_PCIE_DEVICE_CONTROL PcieDev; + UINT32 Offset; + EFI_STATUS Status; + EFI_TPL OldTpl; + + PcieDev.Uint16 =3D 0; + Offset =3D PciDevice->PciExpressCapabilityOffset + + OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl); + Status =3D PciDevice->PciIo.Pci.Read ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &PcieDev.Uint16 + ); + ASSERT (Status =3D=3D EFI_SUCCESS); + + if (PcieDev.Bits.MaxReadRequestSize !=3D PciDevice->SetupMRRS) { + PcieDev.Bits.MaxReadRequestSize =3D PciDevice->SetupMRRS; + DEBUG (( DEBUG_INFO, "MRRS: %d,", PciDevice->SetupMRRS)); + + // + // Raise TPL to high level to disable timer interrupt while the write = operation completes + // + OldTpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + + Status =3D PciDevice->PciIo.Pci.Write ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &PcieDev.Uint16 + ); + // + // Restore TPL to its original level + // + gBS->RestoreTPL (OldTpl); + + if (!EFI_ERROR(Status)) { + PciDevice->PciExpressCapabilityStructure.DeviceControl.Uint16 =3D Pc= ieDev.Uint16; + } else { + ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, = PciDevice->FunctionNumber, Offset); + } + } else { + DEBUG (( DEBUG_INFO, "No MRRS=3D%d,", PciDevice->SetupMRRS)); + } + + return Status; +} + diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h index 460437b..b43fba7 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h @@ -52,4 +52,49 @@ ProgramMaxPayloadSize ( IN VOID *PciExFeatureConfiguration ); =20 + +EFI_STATUS +ConditionalCasMaxReadReqSize ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciFeaturesConfigurationT= able + ); + +/** + 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 B= ase + specification Revision 4, that aligns the value for the entire PCI heira= rchy + starting from its physical PCI Root port / Bridge device. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciConfigPhase for the PCI feature configuration = phases: + PciExpressFeatureSetupPhase & PciE= xpressFeatureEntendedSetupPhase + @param PciFeaturesConfigurationTable pointer to PCI_EXPRESS_FEATURES_CO= NFIGURATION_TABLE + + @retval EFI_SUCCESS processing of PCI feature Max_Read= _Req_Size + is successful. +**/ +EFI_STATUS +SetupMaxReadReqSize ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciFeaturesConfigurationT= able + ); + +/** + Overrides the PCI Device Control register Max_Read_Req_Size register fie= ld; 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 P= CI controller. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramMaxReadReqSize ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExFeatureConfiguration + ); + #endif diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c index aae6139..1caf1f4 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c @@ -34,7 +34,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY mPciExpressPl= atformPolicy =3D { // // support for PCI Express feature - Max. Read Request Size // - FALSE, + TRUE, // // support for PCI Express feature - Extended Tag // @@ -104,6 +104,15 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT mPciExpressF= eatureInitializationList[] }, { PciExpressFeatureProgramPhase, PciExpressMps, ProgramMax= PayloadSize + }, + { + PciExpressFeatureSetupPhase, PciExpressMrrs, SetupMaxRe= adReqSize + }, + { + PciExpressFeatureEntendedSetupPhase, PciExpressMrrs, Conditiona= lCasMaxReadReqSize + }, + { + PciExpressFeatureProgramPhase, PciExpressMrrs, ProgramMax= ReadReqSize } }; =20 @@ -607,6 +616,15 @@ CreatePciRootBridgeDeviceNode ( // start by assuming 4096B as the default value for the Max. Payload S= ize // PciConfigTable->Max_Payload_Size =3D PCIE_MAX_PAYLOAD_SIZE_= 4096B; + // + // start by assuming 4096B as the default value for the Max. Read Requ= est Size + // + PciConfigTable->Max_Read_Request_Size =3D PCIE_MAX_READ_REQ_SIZE= _4096B; + // + // start by assuming the Max. Read Request Size need not be common for= all + // the devices in the PCI tree + // + PciConfigTable->Lock_Max_Read_Request_Size =3D FALSE; } =20 RootBridgeNode->PciExFeaturesConfigurationTable =3D PciConfigTable; diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h index 4ecbefc..a1fc39c 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h @@ -71,6 +71,15 @@ struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE { // size among all the PCI devices in the PCI hierarchy // UINT8 Max_Payload_Size; + // + // to configure the PCI feature maximum read request size to maintain th= e 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; }; =20 // diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c index 3e9d4c5..f74e566 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c @@ -115,6 +115,40 @@ SetDevicePolicyPciExpressMps ( } } =20 +/** + Routine to translate the given device-specific platform policy from type + EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE to HW-specific value, as per PCI Base = Specification + Revision 4.0; for the PCI feature Max_Read_Req_Size. + + @param MRRS Input device-specific policy should be in terms of type + EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE + + @retval Range values for the Max_Read_Req_Size as defined in the= PCI + Base Specification 4.0 +**/ +UINT8 +SetDevicePolicyPciExpressMrrs ( + IN UINT8 MRRS +) +{ + switch (MRRS) { + case EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_128B: + return PCIE_MAX_READ_REQ_SIZE_128B; + case EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_256B: + return PCIE_MAX_READ_REQ_SIZE_256B; + case EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_512B: + return PCIE_MAX_READ_REQ_SIZE_512B; + case EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_1024B: + return PCIE_MAX_READ_REQ_SIZE_1024B; + case EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_2048B: + return PCIE_MAX_READ_REQ_SIZE_2048B; + case EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_4096B: + return PCIE_MAX_READ_REQ_SIZE_4096B; + default: + return PCIE_MAX_READ_REQ_SIZE_128B; + } +} + /** Generic routine to setup the PCI features as per its predetermined defau= lts. **/ @@ -130,6 +164,12 @@ SetupDefaultPciExpressDevicePolicy ( PciDevice->SetupMPS =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; } =20 + if (mPciExpressPlatformPolicy.Mrrs) { + PciDevice->SetupMRRS =3D EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_AUTO; + } else { + PciDevice->SetupMRRS =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; + } + } =20 /** @@ -211,6 +251,14 @@ GetPciExpressDevicePolicy ( PciDevice->SetupMPS =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; } =20 + // + // set device specific policy for Max_Read_Req_Size + // + if (mPciExpressPlatformPolicy.Mrrs) { + PciDevice->SetupMRRS =3D PciExpressDevicePolicy.DeviceCtlMRRS; + } else { + PciDevice->SetupMRRS =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; + } =20 DEBUG (( DEBUG_INFO, @@ -327,6 +375,28 @@ GetPciExpressMps ( return EFI_PCI_EXPRESS_NOT_APPLICABLE; } =20 +EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE +GetPciExpressMrrs ( + IN UINT8 Mrrs + ) +{ + switch (Mrrs) { + case PCIE_MAX_READ_REQ_SIZE_128B: + return EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_128B; + case PCIE_MAX_READ_REQ_SIZE_256B: + return EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_256B; + case PCIE_MAX_READ_REQ_SIZE_512B: + return EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_512B; + case PCIE_MAX_READ_REQ_SIZE_1024B: + return EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_1024B; + case PCIE_MAX_READ_REQ_SIZE_2048B: + return EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_2048B; + case PCIE_MAX_READ_REQ_SIZE_4096B: + return EFI_PCI_EXPRESS_MAX_READ_REQ_SIZE_4096B; + } + return EFI_PCI_EXPRESS_NOT_APPLICABLE; +} + =20 /** Notifies the platform about the current PCI Express state of the device. @@ -358,6 +428,17 @@ PciExpressPlatformNotifyDeviceState ( PciExDeviceConfiguration.DeviceCtlMPS =3D EFI_PCI_EXPRESS_NOT_APPLICAB= LE; } =20 + // + // get the device-specific state for the PCIe Max_Read_Req_Size feature + // + if (mPciExpressPlatformPolicy.Mrrs) { + PciExDeviceConfiguration.DeviceCtlMRRS =3D GetPciExpressMrrs ( + (UINT8)PciDevice->PciExpress= CapabilityStructure.DeviceControl.Bits.MaxReadRequestSize + ); + } else { + PciExDeviceConfiguration.DeviceCtlMRRS =3D EFI_PCI_EXPRESS_NOT_APPLICA= BLE; + } + if (mPciExPlatformProtocol !=3D NULL) { return mPciExPlatformProtocol->NotifyDeviceState ( mPciExPlatformProtocol, diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h index 5ae6386..4653c79 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.h @@ -101,4 +101,19 @@ SetDevicePolicyPciExpressMps ( IN UINT8 MPS ); =20 +/** + 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 Spe= cification + Revision 4.0; for the PCI feature Max_Read_Req_Size. + + @param MRRS Input device-specific policy should be in terms of type + EFI_PCI_CONF_MAX_READ_REQ_SIZE + + @retval Range values for the Max_Read_Req_Size as defined in the= PCI + Base Specification 4.0 +**/ +UINT8 +SetDevicePolicyPciExpressMrrs ( + IN UINT8 MRRS +); #endif --=20 2.21.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#54067): https://edk2.groups.io/g/devel/message/54067 Mute This Topic: https://groups.io/mt/71063078/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 19 14:36:52 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+54068+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+54068+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1581105980670313.3548455083744; Fri, 7 Feb 2020 12:06:20 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id YGpGYY1788612x5B3drr9HSz; Fri, 07 Feb 2020 12:06:20 -0800 X-Received: from mga18.intel.com (mga18.intel.com []) by mx.groups.io with SMTP id smtpd.web09.10529.1581105978095314348 for ; Fri, 07 Feb 2020 12:06:19 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Feb 2020 12:06:19 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,414,1574150400"; d="scan'208";a="225644236" X-Received: from unknown (HELO PIDSBABIOS005.gar.corp.intel.com) ([10.223.9.183]) by fmsmga007.fm.intel.com with ESMTP; 07 Feb 2020 12:06:17 -0800 From: "Javeed, Ashraf" To: devel@edk2.groups.io Cc: Jian J Wang , Hao A Wu , Ray Ni Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 05/12] PciBusDxe: New PCI Express feature Relax Ordering Date: Sat, 8 Feb 2020 01:34:40 +0530 Message-Id: <20200207200447.10536-6-ashraf.javeed@intel.com> In-Reply-To: <20200207200447.10536-1-ashraf.javeed@intel.com> References: <20200207200447.10536-1-ashraf.javeed@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ashraf.javeed@intel.com X-Gm-Message-State: 7fFmXD9TdXBQzwKEvijj4rRix1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1581105980; bh=QYsipPdjxW0QsQMDSCto2Bb33DVaJQfubdVPae9bodg=; h=Cc:Date:From:Reply-To:Subject:To; b=NYmDwbpek/Tvefyl7ziFoCeLG1YY26SQbV2XCNe5+tTsMWYCtCP6i3AxavlQrNdlczM fY+qr1gsTHu1KU7B2npWfX6YneBxgFsBujDRbO+MdOW3Uh/CvAUpByzEwLWbmlmXDRhPV kz6bXLrIStNvgfSmXIacfo8dwF7fiVCWkCw= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2313 The code changes are made to enable the configuration of PCI Express feature Relax Ordering (OR), that enables the PCI function to initiate requests if it does not require strong write ordering for its transact- ions; as per the PCI Express Base Specification 4 Revision 1. The code changes are made to configure only those PCI devices which are requested by platform for override, through the new PCI Express Platform protocol interface for device-specific policies. Signed-off-by: Ashraf Javeed Cc: Jian J Wang Cc: Hao A Wu Cc: Ray Ni --- MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h | 4 ++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c | 70 +++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h | 18 ++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c | 5 ++++- MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 61 +++++++++++++++++= ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 157 insertions(+), 1 deletion(-) diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci= /PciBusDxe/PciBus.h index 77b44c0..d3d795d 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h @@ -287,8 +287,12 @@ struct _PCI_IO_DEVICE { // This field is used to support this case. // UINT16 BridgeIoAlignment; + // + // PCI Express features setup flags + // UINT8 SetupMPS; UINT8 SetupMRRS; + PCI_FEATURE_POLICY SetupRO; }; =20 #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c index 2810158..3262b76 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c @@ -381,3 +381,73 @@ ProgramMaxReadReqSize ( return Status; } =20 +/** + 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 P= CI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramRelaxOrder ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExFeatureConfiguration + ) +{ + PCI_REG_PCIE_DEVICE_CONTROL PcieDev; + UINT32 Offset; + EFI_STATUS Status; + EFI_TPL OldTpl; + + PcieDev.Uint16 =3D 0; + Offset =3D PciDevice->PciExpressCapabilityOffset + + OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl); + Status =3D PciDevice->PciIo.Pci.Read ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &PcieDev.Uint16 + ); + ASSERT (Status =3D=3D EFI_SUCCESS); + + if (PciDevice->SetupRO.Override + && PcieDev.Bits.RelaxedOrdering !=3D PciDevice->SetupRO.Act + ) { + PcieDev.Bits.RelaxedOrdering =3D PciDevice->SetupRO.Act; + DEBUG (( DEBUG_INFO, "RO=3D%d,", PciDevice->SetupRO.Act)); + + // + // Raise TPL to high level to disable timer interrupt while the write = operation completes + // + OldTpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + + Status =3D PciDevice->PciIo.Pci.Write ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &PcieDev.Uint16 + ); + // + // Restore TPL to its original level + // + gBS->RestoreTPL (OldTpl); + + if (!EFI_ERROR(Status)) { + PciDevice->PciExpressCapabilityStructure.DeviceControl.Uint16 =3D Pc= ieDev.Uint16; + } else { + ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, = PciDevice->FunctionNumber, Offset); + } + } else { + DEBUG (( DEBUG_INFO, "No RO,", PciDevice->SetupRO.Act)); + } + + return Status; +} + diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h index b43fba7..0d17801 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h @@ -97,4 +97,22 @@ ProgramMaxReadReqSize ( IN VOID *PciExFeatureConfiguration ); =20 +/** + 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 P= CI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramRelaxOrder ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExFeatureConfiguration + ); + #endif diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c index 1caf1f4..267f570 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c @@ -42,7 +42,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY mPciExpressPl= atformPolicy =3D { // // support for PCI Express feature - Relax Order // - FALSE, + TRUE, // // support for PCI Express feature - No-Snoop // @@ -113,6 +113,9 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT mPciExpressFe= atureInitializationList[] }, { PciExpressFeatureProgramPhase, PciExpressMrrs, ProgramMax= ReadReqSize + }, + { + PciExpressFeatureProgramPhase, PciExpressRelaxOrder, ProgramRel= axOrder } }; =20 diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c index f74e566..40eb8a3 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c @@ -149,6 +149,45 @@ SetDevicePolicyPciExpressMrrs ( } } =20 +/** + Routine to set the device-specific policy for the PCI feature Relax Orde= ring + + @param RelaxOrder value corresponding to data type EFI_PCI_EXPRESS_R= ELAX_ORDER + @param PciDevice A pointer to PCI_IO_DEVICE +**/ +VOID +SetDevicePolicyPciExpressRo ( + IN EFI_PCI_EXPRESS_RELAX_ORDER RelaxOrder, + OUT PCI_IO_DEVICE *PciDevice + ) +{ + // + // implementation specific rules for the usage of PCI_FEATURE_POLICY mem= bers + // exclusively for the PCI Feature Relax Ordering (RO) + // + // .Override =3D 0 to skip this PCI feature RO for the PCI device + // .Override =3D 1 to program this RO PCI feature + // .Act =3D 1 to enable the RO in the PCI device + // .Act =3D 0 to disable the RO in the PCI device + // + switch (RelaxOrder) { + case EFI_PCI_EXPRESS_RO_AUTO: + PciDevice->SetupRO.Override =3D 0; + break; + case EFI_PCI_EXPRESS_RO_DISABLE: + PciDevice->SetupRO.Override =3D 1; + PciDevice->SetupRO.Act =3D 0; + break; + case EFI_PCI_EXPRESS_RO_ENABLE: + PciDevice->SetupRO.Override =3D 1; + PciDevice->SetupRO.Act =3D 1; + break; + default: + PciDevice->SetupRO.Override =3D 0; + break; + } +} + /** Generic routine to setup the PCI features as per its predetermined defau= lts. **/ @@ -170,6 +209,8 @@ SetupDefaultPciExpressDevicePolicy ( PciDevice->SetupMRRS =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; } =20 + PciDevice->SetupRO.Override =3D 0; + } =20 /** @@ -259,6 +300,15 @@ GetPciExpressDevicePolicy ( } else { PciDevice->SetupMRRS =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; } + // + // set device specific policy for Relax Ordering + // + if (mPciExpressPlatformPolicy.RelaxOrder) { + SetDevicePolicyPciExpressRo (PciExpressDevicePolicy.DeviceCtlRelaxOr= der, PciDevice); + } else { + PciDevice->SetupRO.Override =3D 0; + } + =20 DEBUG (( DEBUG_INFO, @@ -438,6 +488,17 @@ PciExpressPlatformNotifyDeviceState ( } else { PciExDeviceConfiguration.DeviceCtlMRRS =3D EFI_PCI_EXPRESS_NOT_APPLICA= BLE; } + // + // get the device-specific state for the PCIe Relax Order feature + // + if (mPciExpressPlatformPolicy.RelaxOrder) { + PciExDeviceConfiguration.DeviceCtlRelaxOrder =3D PciDevice->PciExpress= CapabilityStructure.DeviceControl.Bits.RelaxedOrdering + ? EFI_PCI_EXPRESS_RO= _ENABLE + : EFI_PCI_EXPRESS_RO= _DISABLE; + } else { + PciExDeviceConfiguration.DeviceCtlRelaxOrder =3D EFI_PCI_EXPRESS_NOT_A= PPLICABLE; + } + =20 if (mPciExPlatformProtocol !=3D NULL) { return mPciExPlatformProtocol->NotifyDeviceState ( --=20 2.21.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#54068): https://edk2.groups.io/g/devel/message/54068 Mute This Topic: https://groups.io/mt/71063079/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 19 14:36:52 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+54069+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+54069+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1581105982788598.9638590018247; Fri, 7 Feb 2020 12:06:22 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id PE0aYY1788612xz4tUp6TulF; Fri, 07 Feb 2020 12:06:22 -0800 X-Received: from mga18.intel.com (mga18.intel.com []) by mx.groups.io with SMTP id smtpd.web09.10529.1581105978095314348 for ; Fri, 07 Feb 2020 12:06:22 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Feb 2020 12:06:21 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,414,1574150400"; d="scan'208";a="225644248" X-Received: from unknown (HELO PIDSBABIOS005.gar.corp.intel.com) ([10.223.9.183]) by fmsmga007.fm.intel.com with ESMTP; 07 Feb 2020 12:06:19 -0800 From: "Javeed, Ashraf" To: devel@edk2.groups.io Cc: Jian J Wang , Hao A Wu , Ray Ni Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 06/12] PciBusDxe: New PCI Express feature No-Snoop Date: Sat, 8 Feb 2020 01:34:41 +0530 Message-Id: <20200207200447.10536-7-ashraf.javeed@intel.com> In-Reply-To: <20200207200447.10536-1-ashraf.javeed@intel.com> References: <20200207200447.10536-1-ashraf.javeed@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ashraf.javeed@intel.com X-Gm-Message-State: rDFlNBFIg4HBGzmRWLO2hhA2x1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1581105982; bh=J9+EwU+dfpveA8AA9sgRU8WPW+C5nFN4Seuvd96uuhM=; h=Cc:Date:From:Reply-To:Subject:To; b=wrni8pcRoj3ee3gr1UBV3fwtP0kHD4AMA67N/JMiZOwhRG5uI5Bw2cTY8x0ugPYIOvk /5JF2kgudvpFmZuXa/Up56+OLR8j3rFLy5KtzY4dDQlPHqexbHI+W5d0WkNzHHaS2Wbde r/9E3doJnO0U/mnLFYDK8aUB4Q7j8TcaiKw= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2313 The code changes are made; as per the PCI Express Base Specification 4 Revision 1; to enable the configuration of PCI Express feature No-Snoop (NS), that enables the PCI function to initiate requests if it does not require hardware enforced cache-coherency for its transactions. The code changes are made to configure only those PCI devices which are requested by platform for override through the new PCI Express Platform protocol interface for device-specific policies. Signed-off-by: Ashraf Javeed Cc: Jian J Wang Cc: Hao A Wu Cc: Ray Ni --- MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h | 1 + MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c | 70 +++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h | 18 ++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c | 5 ++++- MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 62 +++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 155 insertions(+), 1 deletion(-) diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci= /PciBusDxe/PciBus.h index d3d795d..e610b52 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h @@ -293,6 +293,7 @@ struct _PCI_IO_DEVICE { UINT8 SetupMPS; UINT8 SetupMRRS; PCI_FEATURE_POLICY SetupRO; + PCI_FEATURE_POLICY SetupNS; }; =20 #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c index 3262b76..df85366 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c @@ -451,3 +451,73 @@ ProgramRelaxOrder ( return Status; } =20 +/** + 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 P= CI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramNoSnoop ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExFeatureConfiguration + ) +{ + PCI_REG_PCIE_DEVICE_CONTROL PcieDev; + UINT32 Offset; + EFI_STATUS Status; + EFI_TPL OldTpl; + + PcieDev.Uint16 =3D 0; + Offset =3D PciDevice->PciExpressCapabilityOffset + + OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl); + Status =3D PciDevice->PciIo.Pci.Read ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &PcieDev.Uint16 + ); + ASSERT (Status =3D=3D EFI_SUCCESS); + + if (PciDevice->SetupNS.Override + && PcieDev.Bits.NoSnoop !=3D PciDevice->SetupNS.Act + ) { + PcieDev.Bits.NoSnoop =3D PciDevice->SetupNS.Act; + DEBUG (( DEBUG_INFO, "NS=3D%d", PciDevice->SetupNS.Act)); + + // + // Raise TPL to high level to disable timer interrupt while the write = operation completes + // + OldTpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + + Status =3D PciDevice->PciIo.Pci.Write ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &PcieDev.Uint16 + ); + // + // Restore TPL to its original level + // + gBS->RestoreTPL (OldTpl); + + if (!EFI_ERROR(Status)) { + PciDevice->PciExpressCapabilityStructure.DeviceControl.Uint16 =3D Pc= ieDev.Uint16; + } else { + ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, = PciDevice->FunctionNumber, Offset); + } + } else { + DEBUG (( DEBUG_INFO, "No NS,", PciDevice->SetupRO.Act)); + } + + return Status; +} + diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h index 0d17801..ee636ce 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h @@ -115,4 +115,22 @@ ProgramRelaxOrder ( IN VOID *PciExFeatureConfiguration ); =20 +/** + 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 P= CI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramNoSnoop ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExFeatureConfiguration + ); + #endif diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c index 267f570..d264d13 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c @@ -46,7 +46,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY mPciExpressPl= atformPolicy =3D { // // support for PCI Express feature - No-Snoop // - FALSE, + TRUE, // // support for PCI Express feature - ASPM state // @@ -116,6 +116,9 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT mPciExpressFe= atureInitializationList[] }, { PciExpressFeatureProgramPhase, PciExpressRelaxOrder, ProgramRel= axOrder + }, + { + PciExpressFeatureProgramPhase, PciExpressNoSnoop, ProgramNoS= noop } }; =20 diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c index 40eb8a3..954ce16 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c @@ -188,6 +188,46 @@ SetDevicePolicyPciExpressRo ( } } =20 +/** + Routine to set the device-specific policy for the PCI feature No-Snoop e= nable + or disable + + @param NoSnoop value corresponding to data type EFI_PCI_EXPRESS_N= O_SNOOP + @param PciDevice A pointer to PCI_IO_DEVICE +**/ +VOID +SetDevicePolicyPciExpressNs ( + IN EFI_PCI_EXPRESS_NO_SNOOP NoSnoop, + OUT PCI_IO_DEVICE *PciDevice + ) +{ + // + // implementation specific rules for the usage of PCI_FEATURE_POLICY mem= bers + // exclusively for the PCI Feature No-Snoop + // + // .Override =3D 0 to skip this PCI feature No-Snoop for the PCI device + // .Override =3D 1 to program this No-Snoop PCI feature + // .Act =3D 1 to enable the No-Snoop in the PCI device + // .Act =3D 0 to disable the No-Snoop in the PCI device + // + switch (NoSnoop) { + case EFI_PCI_EXPRESS_NS_AUTO: + PciDevice->SetupNS.Override =3D 0; + break; + case EFI_PCI_EXPRESS_NS_DISABLE: + PciDevice->SetupNS.Override =3D 1; + PciDevice->SetupNS.Act =3D 0; + break; + case EFI_PCI_EXPRESS_NS_ENABLE: + PciDevice->SetupNS.Override =3D 1; + PciDevice->SetupNS.Act =3D 1; + break; + default: + PciDevice->SetupNS.Override =3D 0; + break; + } +} + /** Generic routine to setup the PCI features as per its predetermined defau= lts. **/ @@ -211,6 +251,8 @@ SetupDefaultPciExpressDevicePolicy ( =20 PciDevice->SetupRO.Override =3D 0; =20 + PciDevice->SetupNS.Override =3D 0; + } =20 /** @@ -309,6 +351,15 @@ GetPciExpressDevicePolicy ( PciDevice->SetupRO.Override =3D 0; } =20 + // + // set the device specific policy for No-Snoop + // + if (mPciExpressPlatformPolicy.NoSnoop) { + SetDevicePolicyPciExpressNs (PciExpressDevicePolicy.DeviceCtlNoSnoop= , PciDevice); + } else { + PciDevice->SetupNS.Override =3D 0; + } + =20 DEBUG (( DEBUG_INFO, @@ -499,6 +550,17 @@ PciExpressPlatformNotifyDeviceState ( PciExDeviceConfiguration.DeviceCtlRelaxOrder =3D EFI_PCI_EXPRESS_NOT_A= PPLICABLE; } =20 + // + // get the device-specific state for the PCIe NoSnoop feature + // + if (mPciExpressPlatformPolicy.NoSnoop) { + PciExDeviceConfiguration.DeviceCtlNoSnoop =3D PciDevice->PciExpressCap= abilityStructure.DeviceControl.Bits.NoSnoop + ? EFI_PCI_EXPRESS_NS_E= NABLE + : EFI_PCI_EXPRESS_NS_D= ISABLE; + } else { + PciExDeviceConfiguration.DeviceCtlNoSnoop =3D EFI_PCI_EXPRESS_NOT_APPL= ICABLE; + } + =20 if (mPciExPlatformProtocol !=3D NULL) { return mPciExPlatformProtocol->NotifyDeviceState ( --=20 2.21.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#54069): https://edk2.groups.io/g/devel/message/54069 Mute This Topic: https://groups.io/mt/71063081/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 19 14:36:52 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+54070+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+54070+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1581105985814507.1785034175273; Fri, 7 Feb 2020 12:06:25 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id 9FjYYY1788612xeyDnoZu6Lb; Fri, 07 Feb 2020 12:06:25 -0800 X-Received: from mga18.intel.com (mga18.intel.com []) by mx.groups.io with SMTP id smtpd.web09.10529.1581105978095314348 for ; Fri, 07 Feb 2020 12:06:24 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Feb 2020 12:06:24 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,414,1574150400"; d="scan'208";a="225644272" X-Received: from unknown (HELO PIDSBABIOS005.gar.corp.intel.com) ([10.223.9.183]) by fmsmga007.fm.intel.com with ESMTP; 07 Feb 2020 12:06:21 -0800 From: "Javeed, Ashraf" To: devel@edk2.groups.io Cc: Jian J Wang , Hao A Wu , Ray Ni Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 07/12] PciBusDxe: New PCI Express feature Completion Timeout Date: Sat, 8 Feb 2020 01:34:42 +0530 Message-Id: <20200207200447.10536-8-ashraf.javeed@intel.com> In-Reply-To: <20200207200447.10536-1-ashraf.javeed@intel.com> References: <20200207200447.10536-1-ashraf.javeed@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ashraf.javeed@intel.com X-Gm-Message-State: 8g9NN5PNeRdxD2OGYjAUc7NEx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1581105985; bh=nCspPPdw95kCbaLzj5fJWtU6gFWz6PacHo5z7WtD0v8=; h=Cc:Date:From:Reply-To:Subject:To; b=ozfz1SZIcLECrf5+DD0KVccHQNDsOTAempJFIhLwTvdIeGO1+XiUDXVDXQqmKGMgh1l JoU87SuCCTDsyG8JhpfREwDn5izdE02B2c8O2pF+CYVlsfwIkuTXuzoOTmwLHIK1qSfTN 0HZ2lXrg7P06aTRkso7ZPCYg7Aa/2UH/PVg= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2313 The code changes are made; as per the PCI Express Base Specification 4 Revision 1; to enable the configuration of PCI Express feature Completion Timeout (CTO), that enables the PCI function to wait on programmed dura- tion for its transactions before timeout, or disable its detection mecha- nism. The code changes are made to configure only those PCI devices which are requested by platform for override through the new PCI Express Platform protocol interface for device-specific policies. The changes are made to also comply with the device-specific capability attributes. The code follows the below implementation specific rules in case the req- uested platform policy does not match with the device-specific capability attributes:- (1) if device is capable of Range A only and if platform ask for any of ranges B, C, D; than this implementation will only program the default range value for the duration of 50us to 50ms (2) if device is capable of Range B, or range B & C, or Ranges B, C & D only and if the platform ask for the Range A; than this implementation will only program the default range value for the duration of 50us to 50ms (3) if the device is capable of Range B only, or the ranges A & B; and if the platform ask for Range C, or Range D values, than this implement- ation will only program the Range B value for the duration of 65ms to 210ms (4) if the device is capable of Ranges B & C, or Ranges A, B, and C; and if the platform ask for Range D values; than this implementation will only program the Range C for the duration of 1s to 3.5s Signed-off-by: Ashraf Javeed Cc: Jian J Wang Cc: Hao A Wu Cc: Ray Ni --- MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h | 1 + MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c | 387 ++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h | 35 ++++++++++++++++= +++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c | 8 +++++++- MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 131 ++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 561 insertions(+), 1 deletion(-) diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci= /PciBusDxe/PciBus.h index e610b52..9b03c12 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h @@ -294,6 +294,7 @@ struct _PCI_IO_DEVICE { UINT8 SetupMRRS; PCI_FEATURE_POLICY SetupRO; PCI_FEATURE_POLICY SetupNS; + PCI_FEATURE_POLICY SetupCTO; }; =20 #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c index df85366..f3f4d39 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c @@ -521,3 +521,390 @@ ProgramNoSnoop ( return Status; } =20 +/** + To determine the CTO Range A values + + @param CtoValue input CTO range value from 0 to 14 + @retval TRUE the given CTO value belongs to Range A + FALSE the given value does not belong to Range A +**/ +BOOLEAN +IsCtoRangeA ( + IN UINT8 CtoValue + ) +{ + switch (CtoValue) { + case PCIE_COMPLETION_TIMEOUT_50US_100US: + case PCIE_COMPLETION_TIMEOUT_1MS_10MS: + return TRUE; + } + return FALSE; +} + +/** + To determine the CTO Range B values + + @param CtoValue input CTO range value from 0 to 14 + @retval TRUE the given CTO value belongs to Range B + FALSE the given value does not belong to Range B +**/ +BOOLEAN +IsCtoRangeB ( + IN UINT8 CtoValue + ) +{ + switch (CtoValue) { + case PCIE_COMPLETION_TIMEOUT_16MS_55MS: + case PCIE_COMPLETION_TIMEOUT_65MS_210MS: + return TRUE; + } + return FALSE; +} + +/** + To determine the CTO Range C values + + @param CtoValue input CTO range value from 0 to 14 + @retval TRUE the given CTO value belongs to Range C + FALSE the given value does not belong to Range C +**/ +BOOLEAN +IsCtoRangeC ( + IN UINT8 CtoValue + ) +{ + switch (CtoValue) { + case PCIE_COMPLETION_TIMEOUT_260MS_900MS: + case PCIE_COMPLETION_TIMEOUT_1S_3_5S: + return TRUE; + } + return FALSE; +} + +/** + To determine the CTO Range D values + + @param CtoValue input CTO range value from 0 to 14 + @retval TRUE the given CTO value belongs to Range D + FALSE the given value does not belong to Range D +**/ +BOOLEAN +IsCtoRangeD ( + IN UINT8 CtoValue + ) +{ + switch (CtoValue) { + case PCIE_COMPLETION_TIMEOUT_4S_13S: + case PCIE_COMPLETION_TIMEOUT_17S_64S: + return TRUE; + } + return FALSE; +} + +/** + The main routine which setup the PCI feature Completion Timeout as per t= he + device-specific platform policy, as well as in complaince with the PCI B= ase + specification Revision 4. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + + @retval EFI_SUCCESS processing of PCI feature CTO is s= uccessful. +**/ +EFI_STATUS +SetupCompletionTimeout ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExFeatureConfiguration + ) +{ + PCI_REG_PCIE_DEVICE_CAPABILITY2 DeviceCap2; + UINT8 CtoRangeValue; + + if (!PciDevice->SetupCTO.Override) { + // + // No override of CTO is required for this device + // + return EFI_SUCCESS; + } + + // + // determine the CTO range values as per its device capability register + // + DeviceCap2.Uint32 =3D PciDevice->PciExpressCapabilityStructure.DeviceCap= ability2.Uint32; + if (!DeviceCap2.Bits.CompletionTimeoutRanges + && !DeviceCap2.Bits.CompletionTimeoutDisable + ) { + // + // device does not support the CTO mechanism, hence no override is app= licable + // + return EFI_SUCCESS; + } + + // + // override the device CTO values if applicable + // + if (PciDevice->SetupCTO.Act) { + // + // program the CTO range values + // + if (DeviceCap2.Bits.CompletionTimeoutRanges) { + CtoRangeValue =3D PCIE_COMPLETION_TIMEOUT_50US_50MS; + // + // in case if the supported CTO range and the requirement from platf= orm + // policy does not match, than the CTO range setting would be based = on + // this driver's implementation specific, and its rules are as follo= ws:- + // + // 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 de= fault + // 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; an= d the + // platform ask for Range C, or Range D values, than this implementa= tion + // will only program the Range B value for the duration of 65ms to 2= 10ms. + // + // 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 =3D 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 th= e default + // range value for the duration of 50us to 50ms. + // + if (IsCtoRangeB (PciDevice->SetupCTO.Support) + || IsCtoRangeC (PciDevice->SetupCTO.Support) + || IsCtoRangeD (PciDevice->SetupCTO.Support) + ) { + CtoRangeValue =3D 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 implementa= tion will + // only program the default range value for the duration of 50us= to 50ms. + // + if (IsCtoRangeA (PciDevice->SetupCTO.Support)) { + CtoRangeValue =3D PCIE_COMPLETION_TIMEOUT_50US_50MS; + } + + if (IsCtoRangeB (PciDevice->SetupCTO.Support)) { + CtoRangeValue =3D 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 implem= entation + // will only program the Range B value for the duration of 65ms = to 210ms. + // + if (IsCtoRangeC (PciDevice->SetupCTO.Support) + || IsCtoRangeD (PciDevice->SetupCTO.Support) + ) { + CtoRangeValue =3D PCIE_COMPLETION_TIMEOUT_65MS_210MS; + } + break; + + case PCIE_COMPLETION_TIMEOUT_RANGE_B_C_SUPPORTED: + if (IsCtoRangeA (PciDevice->SetupCTO.Support)) { + CtoRangeValue =3D PCIE_COMPLETION_TIMEOUT_50US_50MS; + } + + if (IsCtoRangeB (PciDevice->SetupCTO.Support) + || IsCtoRangeC (PciDevice->SetupCTO.Support) + ) { + CtoRangeValue =3D 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 implementat= ion will + // only program the Range C for the duration of 1s to 3.5s. + // + if (IsCtoRangeD (PciDevice->SetupCTO.Support)) { + CtoRangeValue =3D PCIE_COMPLETION_TIMEOUT_1S_3_5S; + } + break; + + case PCIE_COMPLETION_TIMEOUT_RANGE_B_C_D_SUPPORTED: + if (IsCtoRangeA (PciDevice->SetupCTO.Support)) { + CtoRangeValue =3D PCIE_COMPLETION_TIMEOUT_50US_50MS; + } + if (IsCtoRangeB (PciDevice->SetupCTO.Support) + || IsCtoRangeC (PciDevice->SetupCTO.Support) + || IsCtoRangeD (PciDevice->SetupCTO.Support) + ) { + CtoRangeValue =3D PciDevice->SetupCTO.Support; + } + break; + + case PCIE_COMPLETION_TIMEOUT_RANGE_A_B_SUPPORTED: + if (IsCtoRangeA (PciDevice->SetupCTO.Support) + || IsCtoRangeB (PciDevice->SetupCTO.Support) + ) { + CtoRangeValue =3D PciDevice->SetupCTO.Support; + } + if (IsCtoRangeC (PciDevice->SetupCTO.Support) + || IsCtoRangeD (PciDevice->SetupCTO.Support) + ) { + CtoRangeValue =3D 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 =3D PciDevice->SetupCTO.Support; + } + if (IsCtoRangeD (PciDevice->SetupCTO.Support)) { + CtoRangeValue =3D 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 =3D PciDevice->SetupCTO.Support; + } + break; + + default: + DEBUG (( + DEBUG_ERROR, + "Invalid CTO range: %d\n", + DeviceCap2.Bits.CompletionTimeoutRanges + )); + return EFI_INVALID_PARAMETER; + } + + if (PciDevice->SetupCTO.Support !=3D CtoRangeValue) { + PciDevice->SetupCTO.Support =3D CtoRangeValue; + } + } + DEBUG (( DEBUG_INFO, "CTO enable: %d, CTO range: 0x%x,", + PciDevice->SetupCTO.Act, + PciDevice->SetupCTO.Support + )); + } + return EFI_SUCCESS; +} + +/** + Overrides the PCI Device Control2 register Completion Timeout range; if + the hardware value is different than the intended value. + + @param PciDevice A pointer to the PCI_IO_DEVICE instance. + + @retval EFI_SUCCESS The data was read from or written to the P= CI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramCompletionTimeout ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExFeatureConfiguration + ) +{ + PCI_REG_PCIE_DEVICE_CONTROL2 DeviceCtl2; + PCI_REG_PCIE_DEVICE_CAPABILITY2 DeviceCap2; + UINT32 Offset; + EFI_STATUS Status; + EFI_TPL OldTpl; + + if (!PciDevice->SetupCTO.Override) { + // + // No override of CTO is required for this device + // + DEBUG (( DEBUG_INFO, "CTO skipped,")); + return EFI_SUCCESS; + } + + // + // to program the CTO range values, determine in its device capability r= egister + // + DeviceCap2.Uint32 =3D PciDevice->PciExpressCapabilityStructure.DeviceCap= ability2.Uint32; + if (DeviceCap2.Bits.CompletionTimeoutRanges + || DeviceCap2.Bits.CompletionTimeoutDisable) { + // + // device supports the CTO mechanism + // + DeviceCtl2.Uint16 =3D 0; + Offset =3D PciDevice->PciExpressCapabilityOffset + + OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2); + Status =3D PciDevice->PciIo.Pci.Read ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &DeviceCtl2.Uint16 + ); + ASSERT (Status =3D=3D EFI_SUCCESS); + } else { + // + // device does not support the CTO mechanism, hence no override perfor= med + // + 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 !=3D DeviceCtl2.Bits.CompletionTimeout= Value) { + DeviceCtl2.Bits.CompletionTimeoutValue =3D PciDevice->SetupCTO.Suppo= rt; + } + } else { + // + // disable the CTO mechanism in device + // + DeviceCtl2.Bits.CompletionTimeoutValue =3D 0; + DeviceCtl2.Bits.CompletionTimeoutDisable =3D 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 op= eration completes + // + OldTpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + + Status =3D PciDevice->PciIo.Pci.Write ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &DeviceCtl2.Uint16 + ); + // + // Restore TPL to its original level + // + gBS->RestoreTPL (OldTpl); + + if (!EFI_ERROR(Status)) { + PciDevice->PciExpressCapabilityStructure.DeviceControl2.Uint16 =3D Dev= iceCtl2.Uint16; + } else { + ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, Pc= iDevice->FunctionNumber, Offset); + } + return Status; +} + diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h index ee636ce..2ee7d4d 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h @@ -133,4 +133,39 @@ ProgramNoSnoop ( IN VOID *PciExFeatureConfiguration ); =20 +/** + 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 B= ase + specification Revision 4. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciConfigPhase for the PCI feature configuration = phases: + PciExpressFeatureSetupPhase & PciE= xpressFeatureEntendedSetupPhase + + @retval EFI_SUCCESS processing of PCI feature CTO is s= uccessful. +**/ +EFI_STATUS +SetupCompletionTimeout ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExFeatureConfiguration + ); + +/** + Overrides the PCI Device Control2 register Completion Timeout range; if + the hardware value is different than the intended value. + + @param PciDevice A pointer to the PCI_IO_DEVICE instance. + + @retval EFI_SUCCESS The data was read from or written to the P= CI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramCompletionTimeout ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExFeatureConfiguration + ); + #endif diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c index d264d13..d4459f3 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c @@ -74,7 +74,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY mPciExpressPl= atformPolicy =3D { // // support for PCI Express feature - Completion Timeout // - FALSE, + TRUE, // // support for PCI Express feature - Clock Power Management // @@ -119,6 +119,12 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT mPciExpressF= eatureInitializationList[] }, { PciExpressFeatureProgramPhase, PciExpressNoSnoop, ProgramNoS= noop + }, + { + PciExpressFeatureSetupPhase, PciExpressCto, SetupCompl= etionTimeout + }, + { + PciExpressFeatureProgramPhase, PciExpressCto, ProgramCom= pletionTimeout } }; =20 diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c index 954ce16..1afea19 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c @@ -228,6 +228,85 @@ SetDevicePolicyPciExpressNs ( } } =20 +/** + Routine to set the device-specific policy for the PCI feature CTO value = range + or disable + + @param CtoSupport value corresponding to data type EFI_PCI_EXPRESS_C= TO_SUPPORT + @param PciDevice A pointer to PCI_IO_DEVICE +**/ +VOID +SetDevicePolicyPciExpressCto ( + IN EFI_PCI_EXPRESS_CTO_SUPPORT CtoSupport, + OUT PCI_IO_DEVICE *PciDevice +) +{ + // + // implementation specific rules for the usage of PCI_FEATURE_POLICY mem= bers + // exclusively for the PCI Feature CTO + // + // .Override =3D 0 to skip this PCI feature CTO for the PCI device + // .Override =3D 1 to program this CTO PCI feature + // .Act =3D 1 to program the CTO range as per given device policy i= n .Support + // .Act =3D 0 to disable the CTO mechanism in the PCI device, CTO s= et to default range + // + switch (CtoSupport) { + case EFI_PCI_EXPRESS_CTO_AUTO: + PciDevice->SetupCTO.Override =3D 0; + break; + case EFI_PCI_EXPRESS_CTO_DEFAULT: + PciDevice->SetupCTO.Override =3D 1; + PciDevice->SetupCTO.Act =3D 1; + PciDevice->SetupCTO.Support =3D PCIE_COMPLETION_TIMEOUT_50US_50MS; + break; + case EFI_PCI_EXPRESS_CTO_RANGE_A1: + PciDevice->SetupCTO.Override =3D 1; + PciDevice->SetupCTO.Act =3D 1; + PciDevice->SetupCTO.Support =3D PCIE_COMPLETION_TIMEOUT_50US_100US; + break; + case EFI_PCI_EXPRESS_CTO_RANGE_A2: + PciDevice->SetupCTO.Override =3D 1; + PciDevice->SetupCTO.Act =3D 1; + PciDevice->SetupCTO.Support =3D PCIE_COMPLETION_TIMEOUT_1MS_10MS; + break; + case EFI_PCI_EXPRESS_CTO_RANGE_B1: + PciDevice->SetupCTO.Override =3D 1; + PciDevice->SetupCTO.Act =3D 1; + PciDevice->SetupCTO.Support =3D PCIE_COMPLETION_TIMEOUT_16MS_55MS; + break; + case EFI_PCI_EXPRESS_CTO_RANGE_B2: + PciDevice->SetupCTO.Override =3D 1; + PciDevice->SetupCTO.Act =3D 1; + PciDevice->SetupCTO.Support =3D PCIE_COMPLETION_TIMEOUT_65MS_210MS; + break; + case EFI_PCI_EXPRESS_CTO_RANGE_C1: + PciDevice->SetupCTO.Override =3D 1; + PciDevice->SetupCTO.Act =3D 1; + PciDevice->SetupCTO.Support =3D PCIE_COMPLETION_TIMEOUT_260MS_900MS; + break; + case EFI_PCI_EXPRESS_CTO_RANGE_C2: + PciDevice->SetupCTO.Override =3D 1; + PciDevice->SetupCTO.Act =3D 1; + PciDevice->SetupCTO.Support =3D PCIE_COMPLETION_TIMEOUT_1S_3_5S; + break; + case EFI_PCI_EXPRESS_CTO_RANGE_D1: + PciDevice->SetupCTO.Override =3D 1; + PciDevice->SetupCTO.Act =3D 1; + PciDevice->SetupCTO.Support =3D PCIE_COMPLETION_TIMEOUT_4S_13S; + break; + case EFI_PCI_EXPRESS_CTO_RANGE_D2: + PciDevice->SetupCTO.Override =3D 1; + PciDevice->SetupCTO.Act =3D 1; + PciDevice->SetupCTO.Support =3D PCIE_COMPLETION_TIMEOUT_17S_64S; + break; + case EFI_PCI_EXPRESS_CTO_DET_DISABLE: + PciDevice->SetupCTO.Override =3D 1; + PciDevice->SetupCTO.Act =3D 0; + PciDevice->SetupCTO.Support =3D PCIE_COMPLETION_TIMEOUT_50US_50MS; + break; + } +} + /** Generic routine to setup the PCI features as per its predetermined defau= lts. **/ @@ -253,6 +332,8 @@ SetupDefaultPciExpressDevicePolicy ( =20 PciDevice->SetupNS.Override =3D 0; =20 + PciDevice->SetupCTO.Override =3D 0; + } =20 /** @@ -360,6 +441,15 @@ GetPciExpressDevicePolicy ( PciDevice->SetupNS.Override =3D 0; } =20 + // + // set the device specific policy for Completion Timeout (CTO) + // + if (mPciExpressPlatformPolicy.Cto) { + SetDevicePolicyPciExpressCto (PciExpressDevicePolicy.CTOsupport, Pci= Device); + } else { + PciDevice->SetupCTO.Override =3D 0; + } + =20 DEBUG (( DEBUG_INFO, @@ -498,6 +588,34 @@ GetPciExpressMrrs ( return EFI_PCI_EXPRESS_NOT_APPLICABLE; } =20 +EFI_PCI_EXPRESS_CTO_SUPPORT +GetPciExpressCto ( + IN UINT8 Cto + ) +{ + switch (Cto) { + case PCIE_COMPLETION_TIMEOUT_50US_50MS: + return EFI_PCI_EXPRESS_CTO_DEFAULT; + case PCIE_COMPLETION_TIMEOUT_50US_100US: + return EFI_PCI_EXPRESS_CTO_RANGE_A1; + case PCIE_COMPLETION_TIMEOUT_1MS_10MS: + return EFI_PCI_EXPRESS_CTO_RANGE_A2; + case PCIE_COMPLETION_TIMEOUT_16MS_55MS: + return EFI_PCI_EXPRESS_CTO_RANGE_B1; + case PCIE_COMPLETION_TIMEOUT_65MS_210MS: + return EFI_PCI_EXPRESS_CTO_RANGE_B2; + case PCIE_COMPLETION_TIMEOUT_260MS_900MS: + return EFI_PCI_EXPRESS_CTO_RANGE_C1; + case PCIE_COMPLETION_TIMEOUT_1S_3_5S: + return EFI_PCI_EXPRESS_CTO_RANGE_C2; + case PCIE_COMPLETION_TIMEOUT_4S_13S: + return EFI_PCI_EXPRESS_CTO_RANGE_D1; + case PCIE_COMPLETION_TIMEOUT_17S_64S: + return EFI_PCI_EXPRESS_CTO_RANGE_D2; + } + return EFI_PCI_EXPRESS_NOT_APPLICABLE; +} + =20 /** Notifies the platform about the current PCI Express state of the device. @@ -561,6 +679,19 @@ PciExpressPlatformNotifyDeviceState ( PciExDeviceConfiguration.DeviceCtlNoSnoop =3D EFI_PCI_EXPRESS_NOT_APPL= ICABLE; } =20 + // + // get the device-specific state for the PCIe CTO feature + // + if (mPciExpressPlatformPolicy.Cto) { + PciExDeviceConfiguration.CTOsupport =3D PciDevice->PciExpressCapabilit= yStructure.DeviceControl2.Bits.CompletionTimeoutDisable + ? EFI_PCI_EXPRESS_CTO_DET_DISABLE + : GetPciExpressCto ( + (UINT8)PciDevice->PciExpress= CapabilityStructure.DeviceControl2.Bits.CompletionTimeoutValue + ); + } else { + PciExDeviceConfiguration.CTOsupport =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; + } + =20 if (mPciExPlatformProtocol !=3D NULL) { return mPciExPlatformProtocol->NotifyDeviceState ( --=20 2.21.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#54070): https://edk2.groups.io/g/devel/message/54070 Mute This Topic: https://groups.io/mt/71063084/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 19 14:36:52 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+54071+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+54071+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1581105987823210.7614134506017; Fri, 7 Feb 2020 12:06:27 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id yeBtYY1788612xp8o5v0Yjwv; Fri, 07 Feb 2020 12:06:27 -0800 X-Received: from mga18.intel.com (mga18.intel.com []) by mx.groups.io with SMTP id smtpd.web09.10529.1581105978095314348 for ; Fri, 07 Feb 2020 12:06:26 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Feb 2020 12:06:26 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,414,1574150400"; d="scan'208";a="225644307" X-Received: from unknown (HELO PIDSBABIOS005.gar.corp.intel.com) ([10.223.9.183]) by fmsmga007.fm.intel.com with ESMTP; 07 Feb 2020 12:06:24 -0800 From: "Javeed, Ashraf" To: devel@edk2.groups.io Cc: Jian J Wang , Hao A Wu , Ray Ni Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 08/12] PciBusDxe: New PCI Express feature AtomicOp Date: Sat, 8 Feb 2020 01:34:43 +0530 Message-Id: <20200207200447.10536-9-ashraf.javeed@intel.com> In-Reply-To: <20200207200447.10536-1-ashraf.javeed@intel.com> References: <20200207200447.10536-1-ashraf.javeed@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ashraf.javeed@intel.com X-Gm-Message-State: 4LwDK6CiGSpMN3Quph8Qx86cx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1581105987; bh=8o6Xh+yxDjrWhO9vK0+K40dcOY+vTR51BvRFE3Jravg=; h=Cc:Date:From:Reply-To:Subject:To; b=GFMjpDYBFDLIn7t84o/QdQzoU4bBfEodb2M7vLgP8X11KoX8Of1cg2dVSIn2r8ZavPr GtoI6TFHiJv5s5jyM5tK9r7H6QICjf+IuSZDrxupqlE45bcc2spp2U62kAVWSNloOZygl JDaJwir44Wiel2ZLbQ4quuRgRu9T4G+aPw4= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2499 This code change handles two PCI Express features related to AtomicOp, in compliance with the PCI Express Base SPecification 5: (1) configuring PCI function as an AtomicOp Requester (2) Enabling of Port Egress blocking depending on AtomicOp Routing Capability These is programmed based on the following criteria:- For a PCI Bridge device: - enables as AtomicOp Requester solely based on platform provided device policy - enabling of Port Egress blocking is based on platform device policy; only if its device capability register's AtomicOp Routing bit is 1 For an PCI EndPoint (EP) device: - if the platform's device policy wants to enable the AtomicOp Requester function for this device, than this device is enabled if all its bridge devices have the AtomicOp Routing capability bit set - Enabling of Port Egress disable is not applicable to PCI EP device For an PCI RCiEP device: - the AtomicOp Requester functionality is enabled solely based on the device policy provided by platform - similar to PCI EP device, the enabling of port Egress blocking is not applicable Signed-off-by: Ashraf Javeed Cc: Jian J Wang Cc: Hao A Wu Cc: Ray Ni --- MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h | 1 + MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c | 161 ++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h | 35 ++++++++++++++++= +++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c | 23 ++++++++++++++++= ++++++- MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h | 5 +++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 23 ++++++++++++++++= +++++++ 6 files changed, 247 insertions(+), 1 deletion(-) diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci= /PciBusDxe/PciBus.h index 9b03c12..57ef1b2 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h @@ -295,6 +295,7 @@ struct _PCI_IO_DEVICE { PCI_FEATURE_POLICY SetupRO; PCI_FEATURE_POLICY SetupNS; PCI_FEATURE_POLICY SetupCTO; + EFI_PCI_EXPRESS_ATOMIC_OP SetupAtomicOp; }; =20 #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c index f3f4d39..5c76ba4 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c @@ -908,3 +908,164 @@ ProgramCompletionTimeout ( return Status; } =20 +/** + Routine to setup the AtomicOp Requester in the PCI device, verifies the = routing + support in the bridge devices, to be complaint as per the PCI Base speci= fication. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciExFeatureConfiguration pointer to common configuration ta= ble to + initialize the PCI Express feature + + @retval EFI_SUCCESS bridge device routing capability i= s successful. + EFI_INVALID_PARAMETER input parameter is NULL +**/ +EFI_STATUS +SetupAtomicOpRoutingSupport ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExFeatureConfiguration + ) +{ + // + // to enable the AtomicOp Requester in the PCI EP device; its Root Port = (bridge), + // and its PCIe switch upstream & downstream ports (if present) needs to= support + // the AtomicOp Routing capability. + // + if (IS_PCI_BRIDGE (&PciDevice->Pci)) { + if (!PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Bits.A= tomicOpRouting) { + // + // since the AtomicOp Routing support flag is initialized as TRUE, n= egate + // in case if any of the PCI Bridge device in the PCI tree does not = support + // the AtomicOp Routing capability + // + if (PciExFeatureConfiguration =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + PciExFeatureConfiguration->AtomicOpRoutingSupported =3D FALSE; + } + } + + return EFI_SUCCESS; +} + +/** + Overrides the PCI Device Control 2 register AtomicOp Requester enable fi= eld; 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 P= CI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramAtomicOp ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExFeatureConfiguration + ) +{ + PCI_REG_PCIE_DEVICE_CONTROL2 PcieDev; + UINT32 Offset; + EFI_STATUS Status; + EFI_TPL OldTpl; + + PcieDev.Uint16 =3D 0; + Offset =3D PciDevice->PciExpressCapabilityOffset + + OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2); + Status =3D PciDevice->PciIo.Pci.Read ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &PcieDev.Uint16 + ); + ASSERT (Status =3D=3D EFI_SUCCESS); + + if (PciDevice->SetupAtomicOp.Override) { + // + // override AtomicOp requester device control bit of the device based = on the + // platform request + // + if (IS_PCI_BRIDGE (&PciDevice->Pci)) { + // + // for a bridge device as AtomicOp Requester function; only platform= override + // request is used to set the device control register + // + if (PcieDev.Bits.AtomicOpRequester !=3D PciDevice->SetupAtomicOp.Ena= ble_AtomicOpRequester) { + PcieDev.Bits.AtomicOpRequester =3D PciDevice->SetupAtomicOp.Enable= _AtomicOpRequester; + } + // + // if platform also request its AtomicOp Egress blocking to be enabl= ed; set + // only if its device capability's AtomicOpRouting bit is 1. + // applicable to only the bridge devices + // + if (PciDevice->SetupAtomicOp.Enable_AtomicOpEgressBlocking) { + if (PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Bit= s.AtomicOpRouting) { + PcieDev.Bits.AtomicOpEgressBlocking =3D 1; + } + } + } else { + // + // in the case of non-bridge device + // + if (PciExFeatureConfiguration) { + // + // for a device as AtomicOp Requester function; its bridge devices= should + // support the AtomicOp Routing capability to enable the device's = as a + // requester function + // + if (PciExFeatureConfiguration->AtomicOpRoutingSupported) { + if (PcieDev.Bits.AtomicOpRequester !=3D PciDevice->SetupAtomicOp= .Enable_AtomicOpRequester) { + PcieDev.Bits.AtomicOpRequester =3D PciDevice->SetupAtomicOp.En= able_AtomicOpRequester; + } + } + } else { + // + // for the RCiEP device or the bridge device without any child, se= tup AtomicOp + // Requester as per platform's device policy + // + if (PcieDev.Bits.AtomicOpRequester !=3D PciDevice->SetupAtomicOp.E= nable_AtomicOpRequester) { + PcieDev.Bits.AtomicOpRequester =3D PciDevice->SetupAtomicOp.Enab= le_AtomicOpRequester; + } + } + // + // the enabling of AtomicOp Egress Blocking is not applicable to a n= on-bridge + // device + // + } + DEBUG (( + DEBUG_INFO, + "AtomicOp=3D%d,", + PcieDev.Bits.AtomicOpRequester + )); + + // + // Raise TPL to high level to disable timer interrupt while the write = operation completes + // + OldTpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + + Status =3D PciDevice->PciIo.Pci.Write ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &PcieDev.Uint16 + ); + // + // Restore TPL to its original level + // + gBS->RestoreTPL (OldTpl); + + if (!EFI_ERROR(Status)) { + PciDevice->PciExpressCapabilityStructure.DeviceControl2.Uint16 =3D P= cieDev.Uint16; + } else { + ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, = PciDevice->FunctionNumber, Offset); + } + } else { + DEBUG (( DEBUG_INFO, "No AtomicOp,")); + } + + return Status; +} + diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h index 2ee7d4d..1e287fc 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h @@ -168,4 +168,39 @@ ProgramCompletionTimeout ( IN VOID *PciExFeatureConfiguration ); =20 +/** + Routine to setup the AtomicOp Requester in the PCI device, verifies the = routing + support in the bridge devices, to be complaint as per the PCI Base speci= fication. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciExFeatureConfiguration pointer to common configuration ta= ble to + initialize the PCI Express feature + + @retval EFI_SUCCESS bridge device routing capability i= s successful. + EFI_INVALID_PARAMETER input parameter is NULL +**/ +EFI_STATUS +SetupAtomicOpRoutingSupport ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExFeatureConfiguration + ); + +/** + Overrides the PCI Device Control 2 register AtomicOp Requester enable fi= eld; 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 P= CI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramAtomicOp ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExFeatureConfiguration + ); + #endif diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c index d4459f3..9d624a0 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c @@ -62,7 +62,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY mPciExpressPl= atformPolicy =3D { // // support for PCI Express feature - Atomic Op // - FALSE, + TRUE, // // support for PCI Express feature - LTR // @@ -125,6 +125,12 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT mPciExpressF= eatureInitializationList[] }, { PciExpressFeatureProgramPhase, PciExpressCto, ProgramCom= pletionTimeout + }, + { + PciExpressFeatureSetupPhase, PciExpressAtomicOp, SetupAtomi= cOpRoutingSupport + }, + { + PciExpressFeatureProgramPhase, PciExpressAtomicOp, ProgramAto= micOp } }; =20 @@ -297,6 +303,16 @@ IsPciExpressFeatureExtendedSetupRequired ( && PciExpressPolicy[mPciExpressFeatureInitializationList[idx].PciE= xpressFeatureId] =3D=3D TRUE ) { return TRUE; + } else if ( + // + // the PCI Express feature does not require extended setup phase b= ut it + // does require global flag to track the AtomicOpRouting caoabilit= y to + // be tracked for all its bridge devices + // + idx =3D=3D PciExpressAtomicOp + && PciExpressPolicy[idx] =3D=3D TRUE + ) { + return TRUE; } } =20 @@ -637,6 +653,11 @@ CreatePciRootBridgeDeviceNode ( // the devices in the PCI tree // PciConfigTable->Lock_Max_Read_Request_Size =3D FALSE; + // + // start by assuming the AtomicOp Routing capability is supported in t= he PCI + // tree + // + PciConfigTable->AtomicOpRoutingSupported =3D TRUE; } =20 RootBridgeNode->PciExFeaturesConfigurationTable =3D PciConfigTable; diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h index a1fc39c..2bd565e 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h @@ -80,6 +80,11 @@ struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE { // lock the Max_Read_Request_Size for the entire PCI tree of a root port // BOOLEAN Lock_Max_Read_Request_Size; + // + // to record the AtomicOp Routing capability of the PCI Heirarchy to ena= ble + // the AtomicOp of the EP device + // + BOOLEAN AtomicOpRoutingSupported; }; =20 // diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c index 1afea19..2707976 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c @@ -334,6 +334,8 @@ SetupDefaultPciExpressDevicePolicy ( =20 PciDevice->SetupCTO.Override =3D 0; =20 + PciDevice->SetupAtomicOp.Override =3D 0; + } =20 /** @@ -450,6 +452,14 @@ GetPciExpressDevicePolicy ( PciDevice->SetupCTO.Override =3D 0; } =20 + // + // set the device-specific policy for AtomicOp + // + if (mPciExpressPlatformPolicy.AtomicOp) { + PciDevice->SetupAtomicOp =3D PciExpressDevicePolicy.DeviceCtl2Atomic= Op; + } else { + PciDevice->SetupAtomicOp.Override =3D 0; + } =20 DEBUG (( DEBUG_INFO, @@ -692,6 +702,19 @@ PciExpressPlatformNotifyDeviceState ( PciExDeviceConfiguration.CTOsupport =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; } =20 + // + // get the device-specific state for the PCIe AtomicOp feature + // + if (mPciExpressPlatformPolicy.AtomicOp) { + PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpRequester + =3D (UINT8)PciDevice->PciExpressCapabilityStructure.DeviceControl2.Bit= s.AtomicOpRequester; + PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpEgressBlock= ing + =3D (UINT8)PciDevice->PciExpressCapabilityStructure.DeviceControl2.Bit= s.AtomicOpEgressBlocking; + } else { + PciExDeviceConfiguration.DeviceCtl2AtomicOp.Override =3D 0; + PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpRequester = =3D 0; + PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpEgressBlock= ing =3D 0; + } =20 if (mPciExPlatformProtocol !=3D NULL) { return mPciExPlatformProtocol->NotifyDeviceState ( --=20 2.21.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#54071): https://edk2.groups.io/g/devel/message/54071 Mute This Topic: https://groups.io/mt/71063085/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 19 14:36:52 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+54072+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+54072+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 15811059903651016.146313230474; Fri, 7 Feb 2020 12:06:30 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id 1rEcYY1788612x2kkIcraOod; Fri, 07 Feb 2020 12:06:29 -0800 X-Received: from mga18.intel.com (mga18.intel.com []) by mx.groups.io with SMTP id smtpd.web09.10529.1581105978095314348 for ; Fri, 07 Feb 2020 12:06:29 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Feb 2020 12:06:28 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,414,1574150400"; d="scan'208";a="225644320" X-Received: from unknown (HELO PIDSBABIOS005.gar.corp.intel.com) ([10.223.9.183]) by fmsmga007.fm.intel.com with ESMTP; 07 Feb 2020 12:06:26 -0800 From: "Javeed, Ashraf" To: devel@edk2.groups.io Cc: Jian J Wang , Hao A Wu , Ray Ni Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 09/12] PciBusDxe: New PCI Express feature LTR Date: Sat, 8 Feb 2020 01:34:44 +0530 Message-Id: <20200207200447.10536-10-ashraf.javeed@intel.com> In-Reply-To: <20200207200447.10536-1-ashraf.javeed@intel.com> References: <20200207200447.10536-1-ashraf.javeed@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ashraf.javeed@intel.com X-Gm-Message-State: Tzfie3GFRctwzKFmdOe16Z31x1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1581105989; bh=I4q3SSIpGxyXSoeFs4Cy5Q1wQeuEcuFFXVeFoaGvj0k=; h=Cc:Date:From:Reply-To:Subject:To; b=s11SVPYzStPDM6GJ9QC1BQfPcjMRljkypgSB1QdbWMkxOp3PpvujMD7iXNfGwo+L/In 5lsB3m0FhxerVA2XfeS+irutLEFpA5drPJ/csylPiu94uHKRFoubsxSFJ96DWfXjsnW4i 7aQEQihv9oxcgQDXuXFR7kIu9MOvjCQjhSg= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2499 This code change enables the PCI Express feature LTR, in compliance with the PCI Express Base Specification 5, as well as in accordance its device policy, as follows: (1) all the devices capability register needs to indicate that LTR mecha- nism is supported. ANy device not capable shall lead to all devices state in LTR disable (2) if device policy of any device requests LTR mechanism enabled, than based on above condition (1) is TRUE, all of the devices from root bridge are enabled. (3) Even in case of RCiEP device without any root bridge device; if device policy requests LTR enabled and device capability does not support LTR shall enforce the default LTR disabled state for that device This programming of LTR, gets the device-specific platform policy using the new PCI Express Platform Protocol interface (ECR version 0.8), defined in the below feature request:- https://bugzilla.tianocore.org/show_bug.cgi?id=3D1954 Signed-off-by: Ashraf Javeed Cc: Jian J Wang Cc: Hao A Wu Cc: Ray Ni --- MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h | 1 + MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c | 171 ++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h | 40 ++++++++++++++++= ++++++++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c | 19 ++++++++++++++++= ++- MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h | 9 +++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 53 ++++++++++++++++= +++++++++++++++++++++++++++++++++++++ 6 files changed, 292 insertions(+), 1 deletion(-) diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci= /PciBusDxe/PciBus.h index 57ef1b2..7e43a26 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h @@ -296,6 +296,7 @@ struct _PCI_IO_DEVICE { PCI_FEATURE_POLICY SetupNS; PCI_FEATURE_POLICY SetupCTO; EFI_PCI_EXPRESS_ATOMIC_OP SetupAtomicOp; + BOOLEAN SetupLtr; }; =20 #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c index 5c76ba4..63a243b 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c @@ -1069,3 +1069,174 @@ ProgramAtomicOp ( return Status; } =20 +/** + The main routine which process the PCI feature LTR enable/disable as per= the + device-specific platform policy, as well as in complaince with the PCI E= xpress + Base specification Revision 5. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciExpressConfigurationTable pointer to PCI_EXPRESS_FEATURES_CON= FIGURATION_TABLE + + @retval EFI_SUCCESS setup of PCI feature LTR is succes= sful. +**/ +EFI_STATUS +SetupLtr ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExpressConfigurationTa= ble + ) +{ + PCI_REG_PCIE_DEVICE_CAPABILITY2 DeviceCap2; + // + // as per the PCI-Express Base Specification, in order to enable LTR mec= hanism + // in the upstream ports, all the upstream ports and its downstream port= s has + // to support the LTR mechanism reported in its Device Capability 2 regi= ster + // + DeviceCap2.Uint32 =3D PciDevice->PciExpressCapabilityStructure.DeviceCap= ability2.Uint32; + + if (PciExpressConfigurationTable) { + // + // in this phase establish 2 requirements: + // (1) all the PCI devices in the hierarchy supports the LTR mechanism + // (2) check and record any device-specific platform policy that wants= to + // enable the LTR mechanism + // + if (!PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Bits.L= trMechanism) { + + // + // it starts with the assumption that all the PCI devices support LT= R mechanism + // and negates the flag if any PCI device Device Capability 2 regist= er advertizes + // as not supported + // + PciExpressConfigurationTable->LtrSupported =3D FALSE; + } + + if (PciDevice->SetupLtr =3D=3D TRUE) { + // + // it starts with the assumption that device-specific platform polic= y would + // be set to LTR disable, and negates the flag if any PCI device pla= tform + // policy wants to override to enable the LTR mechanism + // + PciExpressConfigurationTable->LtrEnable =3D TRUE; + } + } else { + // + // in case of RCiEP device or the bridge device with out any child dev= ice, + // overrule the device policy if the device in not capable + // + if (!PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Bits.L= trMechanism + && PciDevice->SetupLtr =3D=3D TRUE) { + PciDevice->SetupLtr =3D FALSE; + } + // + // for any bridge device which is Hot-Plug capable, it is expected tha= t platform + // will not enforce the enabling of LTR mechanism only for the bridge = device + // + } + + DEBUG (( DEBUG_INFO, "LTR En: %d (LTR Cap: %d),", + PciDevice->SetupLtr ? 1 : 0, + PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Bits.LtrMec= hanism + )); + return EFI_SUCCESS; +} + +EFI_STATUS +ReSetupLtr ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExpressConfigurationTa= ble + ) +{ + // + // not applicable to RCiEP device... + // for the bridge device without any child device, the policy is already= overruled + // based on capability in the above routine + // + if (PciExpressConfigurationTable) { + // + // in this phase align the device policy to enable LTR policy of any P= CI device + // in the tree if all the devices are capable to support the LTR mecha= nism + // + if (PciExpressConfigurationTable->LtrSupported =3D=3D TRUE + && PciExpressConfigurationTable->LtrEnable =3D=3D TRUE + ) { + PciDevice->SetupLtr =3D TRUE; + } else { + PciDevice->SetupLtr =3D FALSE; + } + } + + DEBUG (( DEBUG_INFO, "LTR En: %d (LTR Cap: %d),", + PciDevice->SetupLtr ? 1 : 0, + PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Bits.LtrMec= hanism + )); + return EFI_SUCCESS; +} + +/** + Program the PCI Device Control 2 register LTR mechanism field; if + the hardware value is different than the intended value. + + @param PciDevice A pointer to the PCI_IO_DEVICE instance. + + @retval EFI_SUCCESS The data was read from or written to the P= CI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramLtr ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExFeatureConfiguration + ) +{ + PCI_REG_PCIE_DEVICE_CONTROL2 PcieDev; + UINT32 Offset; + EFI_STATUS Status; + EFI_TPL OldTpl; + + PcieDev.Uint16 =3D 0; + Offset =3D PciDevice->PciExpressCapabilityOffset + + OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2); + Status =3D PciDevice->PciIo.Pci.Read ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &PcieDev.Uint16 + ); + ASSERT (Status =3D=3D EFI_SUCCESS); + + if (PciDevice->SetupLtr !=3D (BOOLEAN) PcieDev.Bits.LtrMechanism) { + PcieDev.Bits.LtrMechanism =3D PciDevice->SetupLtr ? 1 : 0; + DEBUG (( DEBUG_INFO, "LTR=3D%d,", PcieDev.Bits.LtrMechanism)); + + // + // Raise TPL to high level to disable timer interrupt while the write = operation completes + // + OldTpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + + Status =3D PciDevice->PciIo.Pci.Write ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &PcieDev.Uint16 + ); + // + // Restore TPL to its original level + // + gBS->RestoreTPL (OldTpl); + + if (!EFI_ERROR(Status)) { + PciDevice->PciExpressCapabilityStructure.DeviceControl2.Uint16 =3D P= cieDev.Uint16; + } else { + ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, = PciDevice->FunctionNumber, Offset); + } + } else { + DEBUG (( DEBUG_INFO, "no LTR,")); + } + + return Status; +} + diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h index 1e287fc..374fe49 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h @@ -203,4 +203,44 @@ ProgramAtomicOp ( IN VOID *PciExFeatureConfiguration ); =20 +/** + The main routine which process the PCI feature LTR enable/disable as per= the + device-specific platform policy, as well as in complaince with the PCI E= xpress + Base specification Revision 5. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciFeaturesConfigurationTable pointer to PCI_EXPRESS_FEATURES_CO= NFIGURATION_TABLE + + @retval EFI_SUCCESS setup of PCI feature LTR is succes= sful. +**/ +EFI_STATUS +SetupLtr ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciFeaturesConfigurationT= able + ); + +EFI_STATUS +ReSetupLtr ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciFeaturesConfigurationT= able + ); + +/** + Program the PCI Device Control 2 register LTR mechanism field; if + the hardware value is different than the intended value. + + @param PciDevice A pointer to the PCI_IO_DEVICE instance. + + @retval EFI_SUCCESS The data was read from or written to the P= CI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramLtr ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExFeatureConfiguration + ); + #endif diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c index 9d624a0..bdeb0d2 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c @@ -66,7 +66,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY mPciExpressPl= atformPolicy =3D { // // support for PCI Express feature - LTR // - FALSE, + TRUE, // // support for PCI Express feature - PTM // @@ -131,6 +131,15 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT mPciExpressF= eatureInitializationList[] }, { PciExpressFeatureProgramPhase, PciExpressAtomicOp, ProgramAto= micOp + }, + { + PciExpressFeatureSetupPhase, PciExpressLtr, SetupLtr + }, + { + PciExpressFeatureEntendedSetupPhase, PciExpressLtr, ReSetupLtr + }, + { + PciExpressFeatureProgramPhase, PciExpressLtr, ProgramLtr } }; =20 @@ -654,6 +663,14 @@ CreatePciRootBridgeDeviceNode ( // PciConfigTable->Lock_Max_Read_Request_Size =3D FALSE; // + // start by assuming the LTR mechanism is supported in a PCI tree + // + PciConfigTable->LtrSupported =3D TRUE; + // + // the default LTR mechanism is disabled as per the PCI Base specifica= tion + // + PciConfigTable->LtrEnable =3D FALSE; + // // start by assuming the AtomicOp Routing capability is supported in t= he PCI // tree // diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h index 2bd565e..5dded7c 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h @@ -81,6 +81,15 @@ struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE { // BOOLEAN Lock_Max_Read_Request_Size; // + // to record the adversity in LTR mechanism support capability among the= PCI + // device of an heirarchy + // + BOOLEAN LtrSupported; + // + // to enable the LTR mechansim for the entire PCI tree from a root port + // + BOOLEAN LtrEnable; + // // to record the AtomicOp Routing capability of the PCI Heirarchy to ena= ble // the AtomicOp of the EP device // diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c index 2707976..83b3aa7 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c @@ -307,6 +307,36 @@ SetDevicePolicyPciExpressCto ( } } =20 +/** + Routine to set the device-specific policy for the PCI feature LTR enable= /disable + + @param AtomicOp value corresponding to data type EFI_PCI_EXPRESS_A= TOMIC_OP + @param PciDevice A pointer to PCI_IO_DEVICE + +**/ +VOID +SetDevicePolicyPciExpressLtr ( + IN EFI_PCI_EXPRESS_LTR Ltr, + OUT PCI_IO_DEVICE *PciDevice + ) +{ + switch (Ltr){ + case EFI_PCI_EXPRESS_LTR_AUTO: + case EFI_PCI_EXPRESS_LTR_DISABLE: + // + // leave the LTR mechanism disable or restore to its default state + // + PciDevice->SetupLtr =3D FALSE; + break; + case EFI_PCI_EXPRESS_LTR_ENABLE: + // + // LTR mechanism enable + // + PciDevice->SetupLtr =3D TRUE; + break; + } +} + /** Generic routine to setup the PCI features as per its predetermined defau= lts. **/ @@ -336,6 +366,8 @@ SetupDefaultPciExpressDevicePolicy ( =20 PciDevice->SetupAtomicOp.Override =3D 0; =20 + PciDevice->SetupLtr =3D FALSE; + } =20 /** @@ -461,6 +493,16 @@ GetPciExpressDevicePolicy ( PciDevice->SetupAtomicOp.Override =3D 0; } =20 + // + // set the device-specific policy for LTR mechanism in the function + // + if (mPciExpressPlatformPolicy.Ltr) { + SetDevicePolicyPciExpressLtr (PciExpressDevicePolicy.DeviceCtl2LTR, = PciDevice); + } else { + PciDevice->SetupLtr =3D FALSE; + } + + DEBUG (( DEBUG_INFO, "[device policy: platform]" @@ -715,6 +757,17 @@ PciExpressPlatformNotifyDeviceState ( PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpRequester = =3D 0; PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpEgressBlock= ing =3D 0; } + // + // get the device-specific state for LTR mechanism in the function + // + if (mPciExpressPlatformPolicy.Ltr) { + PciExDeviceConfiguration.DeviceCtl2LTR =3D PciDevice->PciExpressCapabi= lityStructure.DeviceControl2.Bits.LtrMechanism + ? EFI_PCI_EXPRESS_LTR_ENAB= LE + : EFI_PCI_EXPRESS_LTR_DISA= BLE; + } else { + PciExDeviceConfiguration.DeviceCtl2LTR =3D EFI_PCI_EXPRESS_NOT_APPLICA= BLE; + } + =20 if (mPciExPlatformProtocol !=3D NULL) { return mPciExPlatformProtocol->NotifyDeviceState ( --=20 2.21.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#54072): https://edk2.groups.io/g/devel/message/54072 Mute This Topic: https://groups.io/mt/71063088/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 19 14:36:52 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+54073+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+54073+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1581105993948609.8946315997629; Fri, 7 Feb 2020 12:06:33 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id 2ITvYY1788612xl668pqYSPu; Fri, 07 Feb 2020 12:06:33 -0800 X-Received: from mga18.intel.com (mga18.intel.com []) by mx.groups.io with SMTP id smtpd.web09.10529.1581105978095314348 for ; Fri, 07 Feb 2020 12:06:33 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Feb 2020 12:06:31 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,414,1574150400"; d="scan'208";a="225644334" X-Received: from unknown (HELO PIDSBABIOS005.gar.corp.intel.com) ([10.223.9.183]) by fmsmga007.fm.intel.com with ESMTP; 07 Feb 2020 12:06:28 -0800 From: "Javeed, Ashraf" To: devel@edk2.groups.io Cc: Jian J Wang , Hao A Wu , Ray Ni Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 10/12] PciBusDxe: New PCI Express feature Extended Tag Date: Sat, 8 Feb 2020 01:34:45 +0530 Message-Id: <20200207200447.10536-11-ashraf.javeed@intel.com> In-Reply-To: <20200207200447.10536-1-ashraf.javeed@intel.com> References: <20200207200447.10536-1-ashraf.javeed@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ashraf.javeed@intel.com X-Gm-Message-State: RKhAEgPEJ7p9X2CAXmwGj7i1x1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1581105993; bh=5FO4Ws1OYlHtLtroVpe113S4OdCem6oSfGzCgEPQKgA=; h=Cc:Date:From:Reply-To:Subject:To; b=ctqbN/kJje4jRAuIUXtG5LtN3TUdMFFVjn6WXlWwecBkgCmAb3zt3GnHS6JPaOfmEne bF7TGXr2z4BF/2fBeyb1Aiu9/4d3hBeY1e91IbbDD9am+GXMwHdxbeDxgA2fkESOSiPxS AH5AZ+0Kj7Uy3uLJJ36jdKMDRWXnSm2nH9w= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2499 This code change enables the PCI Express feature Extended Tag, in compliance with the PCI Express Base Specification 5, and uses the device policy under the following conditions: (1) As per the PCI Express Base Specification, all the devices under the root bridge has to be set to a common applicable value (2) The 5b or 8b Extended Tag capability is defined in the Device Capabi- lity register, and the 10b requester as well as completer is defined in the Device Capability 2 register (3) The Extended Tag device policy would be overruled for any device if it does not match with its device capabilities register (4) In case of multiple device policies, due to multiple devices under the root bridge, the lowest applicable value will be programmed for all the devices (5) There is no Extended Tag disable state; hence the default would be 5b or 8b depending upon device HW-state. The 10b requester is disabled by default; hence any device policy request of 10b shall lead to 10b Requester enable state from root bridge to all end devices; if all the devices support 10b Requester as well as the completer capability. In this scenario, the default state of 5b/8b Extended Tag state in Device Control register is ignored as 10b capable devices should be able to handle lower size Extended Tag packet IDs autonomously. This programming of Extended Tag, gets the device-specific platform policy using the new PCI Express Platform Protocol interface (ECR version 0.8), defined in the below feature request:- https://bugzilla.tianocore.org/show_bug.cgi?id=3D1954 Signed-off-by: Ashraf Javeed Cc: Jian J Wang Cc: Hao A Wu Cc: Ray Ni --- MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h | 1 + MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c | 278 ++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h | 50 ++++++++++++++++= ++++++++++++++++++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c | 15 ++++++++++++++- MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h | 4 ++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 36 ++++++++++++++++= ++++++++++++++++++++ 6 files changed, 383 insertions(+), 1 deletion(-) diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci= /PciBusDxe/PciBus.h index 7e43a26..6a6f648 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h @@ -297,6 +297,7 @@ struct _PCI_IO_DEVICE { PCI_FEATURE_POLICY SetupCTO; EFI_PCI_EXPRESS_ATOMIC_OP SetupAtomicOp; BOOLEAN SetupLtr; + UINT8 SetupExtTag; }; =20 #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c index 63a243b..eaef3d3 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c @@ -1240,3 +1240,281 @@ ProgramLtr ( return Status; } =20 +/** + The main routine to setup the PCI Express feature Extended Tag as per the + device-specific platform policy, as well as in complaince with the PCI E= xpress + Base specification Revision 5. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciExpressConfigurationTable pointer to PCI_EXPRESS_FEATURES_CON= FIGURATION_TABLE + + @retval EFI_SUCCESS setup of PCI feature LTR is succes= sful. +**/ +EFI_STATUS +SetupExtTag ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExpressConfigurationTa= ble + ) +{ + PCI_REG_PCIE_DEVICE_CAPABILITY2 DeviceCap2; + PCI_REG_PCIE_DEVICE_CAPABILITY DeviceCap; + EFI_PCI_EXPRESS_EXTENDED_TAG PciExpressExtendedTag; + + DeviceCap.Uint32 =3D PciDevice->PciExpressCapabilityStructure.DeviceCapa= bility.Uint32; + DeviceCap2.Uint32 =3D PciDevice->PciExpressCapabilityStructure.DeviceCap= ability2.Uint32; + // + // The PCI Express feature Extended Tag has to be maintained common from= a + // root bridge device to all its child devices. + // The Device Capability 2 register is used to determine the 10b Extende= d Tag + // capability of a device. The device capability register is used to det= ermine + // 5b/8b Extended Tag capability of a device + // + if (DeviceCap2.Bits.TenBitTagCompleterSupported & DeviceCap2.Bits.TenBit= TagRequesterSupported) { + // + // device supports the 10b Extended Tag capability + // + PciExpressExtendedTag =3D EFI_PCI_EXPRESS_EXTENDED_TAG_10BIT; + } else { + if (DeviceCap.Bits.ExtendedTagField) { + PciExpressExtendedTag =3D EFI_PCI_EXPRESS_EXTENDED_TAG_8BIT; + } else { + PciExpressExtendedTag =3D EFI_PCI_EXPRESS_EXTENDED_TAG_5BIT; + } + } + if (PciDevice->SetupExtTag =3D=3D EFI_PCI_EXPRESS_EXTENDED_TAG_AUTO) { + PciDevice->SetupExtTag =3D PciExpressExtendedTag; + } + // + // in case of PCI Bridge and its child devices + // + if (PciExpressConfigurationTable) { + // + // align the Extended Tag value as per the device supported value + // + PciExpressConfigurationTable->ExtendedTag =3D MIN ( + PciExpressExtendedTag, + PciExpressConfigurationT= able->ExtendedTag + ); + // + // check for any invalid platform policy request for the device; if tr= ue than + // align with the device capability value. Else align as per platform = request + // + if (PciDevice->SetupExtTag > PciExpressConfigurationTable->ExtendedTag= ) { + // + // setup the device Extended Tag to common value supported by all th= e devices + // + PciDevice->SetupExtTag =3D PciExpressConfigurationTable->ExtendedTag; + } + // + // if the platform policy is to downgrade the device's Extended Tag va= lue than + // all the other devices in the PCI tree including the root bridge wil= l be align + // with this device override value + // + if (PciDevice->SetupExtTag < PciExpressConfigurationTable->ExtendedTag= ) { + PciExpressConfigurationTable->ExtendedTag =3D PciDevice->SetupExtTag; + } + } else { + // + // in case of RCiEP devices or the bridge device without any child, ov= errule + // the Extended Tag device policy if it does not match with its capabi= lity + // + PciDevice->SetupExtTag =3D MIN ( + PciDevice->SetupExtTag, + PciExpressExtendedTag + ); + } + + DEBUG (( + DEBUG_INFO, + "ExtTag: %d [cap:%d],", + PciDevice->SetupExtTag, + PciExpressExtendedTag + )); + return EFI_SUCCESS; +} + +/** + Additional routine to setup the PCI Express feature Extended Tag in comp= laince + with the PCI Express Base specification Revision, a common value for all= the + devices in the PCI hierarchy. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciExpressConfigurationTable pointer to PCI_EXPRESS_FEATURES_CON= FIGURATION_TABLE + + @retval EFI_SUCCESS setup of PCI feature LTR is succes= sful. +**/ +EFI_STATUS +AlignExtTag ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExpressConfigurationTa= ble + ) +{ + if (PciExpressConfigurationTable) { + // + // align the Extended Tag value to a common value among all the devices + // + PciDevice->SetupExtTag =3D MIN ( + PciDevice->SetupExtTag, + PciExpressConfigurationTable->ExtendedTag + ); + } + + DEBUG (( + DEBUG_INFO, + "ExtTag: %d,", + PciDevice->SetupExtTag + )); + return EFI_SUCCESS; +} + +/** + Program the PCI Device Control 2 register for 10b Extended Tag value, or= the + Device Control register for 5b/8b Extended Tag value. + + @param PciDevice A pointer to the PCI_IO_DEVICE instance. + + @retval EFI_SUCCESS The data was read from or written to the P= CI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramExtTag ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExFeatureConfiguration + ) +{ + PCI_REG_PCIE_DEVICE_CONTROL DevCtl; + PCI_REG_PCIE_DEVICE_CONTROL2 DevCtl2; + UINT32 Offset; + UINT32 Offset2; + BOOLEAN OverrideDevCtl; + BOOLEAN OverrideDevCtl2; + EFI_STATUS Status; + EFI_TPL OldTpl; + + // + // read the Device Control register for the Extended Tag Field Enable + // + DevCtl.Uint16 =3D 0; + Offset =3D PciDevice->PciExpressCapabilityOffset + + OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl); + Status =3D PciDevice->PciIo.Pci.Read ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &DevCtl.Uint16 + ); + ASSERT (Status =3D=3D EFI_SUCCESS); + + OverrideDevCtl =3D FALSE; + // + // read the Device COntrol 2 register for the 10-Bit Tag Requester Enable + // + DevCtl2.Uint16 =3D 0; + Offset2 =3D PciDevice->PciExpressCapabilityOffset + + OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2); + Status =3D PciDevice->PciIo.Pci.Read ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset2, + 1, + &DevCtl2.Uint16 + ); + ASSERT (Status =3D=3D EFI_SUCCESS); + + OverrideDevCtl2 =3D FALSE; + + if (PciDevice->SetupExtTag =3D=3D EFI_PCI_EXPRESS_EXTENDED_TAG_5BIT) { + if (DevCtl.Bits.ExtendedTagField) { + DevCtl.Bits.ExtendedTagField =3D 0; + OverrideDevCtl =3D TRUE; + } + + if (DevCtl2.Bits.TenBitTagRequesterEnable) { + DevCtl2.Bits.TenBitTagRequesterEnable =3D 0; + OverrideDevCtl2 =3D TRUE; + } + } + if (PciDevice->SetupExtTag =3D=3D EFI_PCI_EXPRESS_EXTENDED_TAG_8BIT) { + if (!DevCtl.Bits.ExtendedTagField) { + DevCtl.Bits.ExtendedTagField =3D 1; + OverrideDevCtl =3D TRUE; + } + if (DevCtl2.Bits.TenBitTagRequesterEnable) { + DevCtl2.Bits.TenBitTagRequesterEnable =3D 0; + OverrideDevCtl2 =3D TRUE; + } + } + if (PciDevice->SetupExtTag =3D=3D EFI_PCI_EXPRESS_EXTENDED_TAG_10BIT) { + if (!DevCtl2.Bits.TenBitTagRequesterEnable) { + DevCtl2.Bits.TenBitTagRequesterEnable =3D 1; + OverrideDevCtl2 =3D TRUE; + } + } + + if (OverrideDevCtl) { + + DEBUG (( DEBUG_INFO, "ExtTag=3D%d,", DevCtl.Bits.ExtendedTagField)); + + // + // Raise TPL to high level to disable timer interrupt while the write = operation completes + // + OldTpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + + Status =3D PciDevice->PciIo.Pci.Write ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &DevCtl.Uint16 + ); + // + // Restore TPL to its original level + // + gBS->RestoreTPL (OldTpl); + + if (!EFI_ERROR(Status)) { + PciDevice->PciExpressCapabilityStructure.DeviceControl.Uint16 =3D De= vCtl.Uint16; + } else { + ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, = PciDevice->FunctionNumber, Offset); + } + } else { + DEBUG (( DEBUG_INFO, "no ExtTag (%d),", DevCtl.Bits.ExtendedTagField)); + } + + if (OverrideDevCtl2) { + + DEBUG (( DEBUG_INFO, "10bExtTag=3D%d,", DevCtl2.Bits.TenBitTagRequeste= rEnable)); + + // + // Raise TPL to high level to disable timer interrupt while the write = operation completes + // + OldTpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + + Status =3D PciDevice->PciIo.Pci.Write ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset2, + 1, + &DevCtl2.Uint16 + ); + // + // Restore TPL to its original level + // + gBS->RestoreTPL (OldTpl); + + if (!EFI_ERROR(Status)) { + PciDevice->PciExpressCapabilityStructure.DeviceControl2.Uint16 =3D D= evCtl2.Uint16; + } else { + ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, = PciDevice->FunctionNumber, Offset2); + } + } else { + DEBUG (( DEBUG_INFO, "no 10bExtTag (%d),", DevCtl2.Bits.TenBitTagReque= sterEnable)); + } + + return Status; +} + diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h index 374fe49..1cfca54 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h @@ -243,4 +243,54 @@ ProgramLtr ( IN VOID *PciExFeatureConfiguration ); =20 +/** + The main routine to setup the PCI Express feature Extended Tag as per the + device-specific platform policy, as well as in complaince with the PCI E= xpress + Base specification Revision 5. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciFeaturesConfigurationTable pointer to PCI_EXPRESS_FEATURES_CO= NFIGURATION_TABLE + + @retval EFI_SUCCESS setup of PCI feature LTR is succes= sful. +**/ +EFI_STATUS +SetupExtTag ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciFeaturesConfigurationT= able + ); + +/** + Additional routine to setup the PCI Express feature Extended Tag in comp= laince + with the PCI Express Base specification Revision, a common value for all= the + devices in the PCI hierarchy. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciFeaturesConfigurationTable pointer to PCI_EXPRESS_FEATURES_CO= NFIGURATION_TABLE + + @retval EFI_SUCCESS setup of PCI feature LTR is succes= sful. +**/ +EFI_STATUS +AlignExtTag ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciFeaturesConfigurationT= able + ); + +/** + Program the PCI Device Control 2 register for 10b Extended Tag value, or= the + Device Control register for 5b/8b Extended Tag value. + + @param PciDevice A pointer to the PCI_IO_DEVICE instance. + + @retval EFI_SUCCESS The data was read from or written to the P= CI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramExtTag ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExFeatureConfiguration + ); + #endif diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c index bdeb0d2..58d3780 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c @@ -38,7 +38,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY mPciExpressPl= atformPolicy =3D { // // support for PCI Express feature - Extended Tag // - FALSE, + TRUE, // // support for PCI Express feature - Relax Order // @@ -140,6 +140,15 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT mPciExpressF= eatureInitializationList[] }, { PciExpressFeatureProgramPhase, PciExpressLtr, ProgramLtr + }, + { + PciExpressFeatureSetupPhase, PciExpressExtTag, SetupExtTag + }, + { + PciExpressFeatureEntendedSetupPhase, PciExpressExtTag, AlignExtTag + }, + { + PciExpressFeatureProgramPhase, PciExpressExtTag, ProgramExt= Tag } }; =20 @@ -675,6 +684,10 @@ CreatePciRootBridgeDeviceNode ( // tree // PciConfigTable->AtomicOpRoutingSupported =3D TRUE; + // + // start by assuming the Extended Tag is 10b Requester capable + // + PciConfigTable->ExtendedTag =3D EFI_PCI_EXPRESS_EXTEND= ED_TAG_10BIT; } =20 RootBridgeNode->PciExFeaturesConfigurationTable =3D PciConfigTable; diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h index 5dded7c..c7cc7e5 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h @@ -94,6 +94,10 @@ struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE { // the AtomicOp of the EP device // BOOLEAN AtomicOpRoutingSupported; + // + // to configure a common extended tag size for all the childs of a root = port + // + UINT8 ExtendedTag; }; =20 // diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c index 83b3aa7..98d9875 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c @@ -368,6 +368,12 @@ SetupDefaultPciExpressDevicePolicy ( =20 PciDevice->SetupLtr =3D FALSE; =20 + if (mPciExpressPlatformPolicy.ExtTag) { + PciDevice->SetupExtTag =3D EFI_PCI_EXPRESS_EXTENDED_TAG_AUTO; + } else { + PciDevice->SetupExtTag =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; + } + } =20 /** @@ -502,6 +508,15 @@ GetPciExpressDevicePolicy ( PciDevice->SetupLtr =3D FALSE; } =20 + // + // set the device-specifci policy for the PCI Express feature Extended= Tag + // + if (mPciExpressPlatformPolicy.ExtTag) { + PciDevice->SetupExtTag =3D PciExpressDevicePolicy.DeviceCtlExtTag; + } else { + PciDevice->SetupExtTag =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; + } + =20 DEBUG (( DEBUG_INFO, @@ -668,6 +683,19 @@ GetPciExpressCto ( return EFI_PCI_EXPRESS_NOT_APPLICABLE; } =20 +EFI_PCI_EXPRESS_EXTENDED_TAG +GetPciExpressExtTag ( + IN PCI_IO_DEVICE *PciDevice + ) +{ + if (PciDevice->PciExpressCapabilityStructure.DeviceControl2.Bits.TenBitT= agRequesterEnable) { + return EFI_PCI_EXPRESS_EXTENDED_TAG_10BIT; + } else if (PciDevice->PciExpressCapabilityStructure.DeviceControl.Bits.E= xtendedTagField) { + return EFI_PCI_EXPRESS_EXTENDED_TAG_8BIT; + } else { + return EFI_PCI_EXPRESS_EXTENDED_TAG_5BIT; + } +} =20 /** Notifies the platform about the current PCI Express state of the device. @@ -768,6 +796,14 @@ PciExpressPlatformNotifyDeviceState ( PciExDeviceConfiguration.DeviceCtl2LTR =3D EFI_PCI_EXPRESS_NOT_APPLICA= BLE; } =20 + // + // get the device-specific state for the PCie Extended Tag in the functi= on + // + if (mPciExpressPlatformPolicy.ExtTag) { + PciExDeviceConfiguration.DeviceCtlExtTag =3D GetPciExpressExtTag (PciD= evice); + } else { + PciExDeviceConfiguration.DeviceCtlExtTag =3D EFI_PCI_EXPRESS_NOT_APPLI= CABLE; + } =20 if (mPciExPlatformProtocol !=3D NULL) { return mPciExPlatformProtocol->NotifyDeviceState ( --=20 2.21.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#54073): https://edk2.groups.io/g/devel/message/54073 Mute This Topic: https://groups.io/mt/71063091/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 19 14:36:52 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+54074+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+54074+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1581105994938868.2980181805757; Fri, 7 Feb 2020 12:06:34 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id HEYWYY1788612xsAI5zC9e37; Fri, 07 Feb 2020 12:06:34 -0800 X-Received: from mga18.intel.com (mga18.intel.com []) by mx.groups.io with SMTP id smtpd.web09.10529.1581105978095314348 for ; Fri, 07 Feb 2020 12:06:34 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Feb 2020 12:06:33 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,414,1574150400"; d="scan'208";a="225644341" X-Received: from unknown (HELO PIDSBABIOS005.gar.corp.intel.com) ([10.223.9.183]) by fmsmga007.fm.intel.com with ESMTP; 07 Feb 2020 12:06:31 -0800 From: "Javeed, Ashraf" To: devel@edk2.groups.io Cc: Jian J Wang , Hao A Wu , Ray Ni Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 11/12] PciBusDxe: New PCI Express feature ASPM support Date: Sat, 8 Feb 2020 01:34:46 +0530 Message-Id: <20200207200447.10536-12-ashraf.javeed@intel.com> In-Reply-To: <20200207200447.10536-1-ashraf.javeed@intel.com> References: <20200207200447.10536-1-ashraf.javeed@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ashraf.javeed@intel.com X-Gm-Message-State: dpfZaniKkG9Lff4bko0Hvoi5x1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1581105994; bh=mF5W20RASJ7UPR9dY/F1niClf56Ct7GdxAxpzUs+UWY=; h=Cc:Date:From:Reply-To:Subject:To; b=XpHQfoGfNtQItDJVz0Xht47sEnb7w8T59lNGqdIibr3i/sDLJe2L2H4u6RJ9LNIa8Bx gsggvrwUlvRIX8ICNJF5TSDauZ/Xv9Mo3pmFJvuLQXyLUOm9tTT2wGVkrFNixhW5mE7aQ hR2w1juNHia/RCanfyz7eB6yf7yMhX/RkYM= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2500 This code change is to enable the common ASPM state for all the connected devices, as per the PCI Express Base Specification 5, Revision 1. This feature is not applicable to RCiEP, and to a vacant bridge device. The device policy request from platform is applied if that is applicable as per its Link Capability register. Since all the connected devices have to have common applicable ASPM value, it would be overuled as per PCI Ex- press Base Specification. The device L0s/L1 Acceptance Latency is used to measure against the L0s/L1 Exit Latencies comprising from Root Bridge to all its EP devices. If not applicable ASPM would be disabled for all the devices. This programming of ASPM, gets the device-specific platform policy using the new PCI Express Platform Protocol interface (ECR version 0.8), defined in the below feature request:- https://bugzilla.tianocore.org/show_bug.cgi?id=3D1954 Signed-off-by: Ashraf Javeed Cc: Jian J Wang Cc: Hao A Wu Cc: Ray Ni --- MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h | 1 + MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c | 391 ++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h | 52 ++++++++++++++++= ++++++++++++++++++++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c | 23 ++++++++++++++++= ++++++- MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h | 14 ++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 45 ++++++++++++++++= +++++++++++++++++++++++++++++ 6 files changed, 525 insertions(+), 1 deletion(-) diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci= /PciBusDxe/PciBus.h index 6a6f648..b5caffe 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h @@ -298,6 +298,7 @@ struct _PCI_IO_DEVICE { EFI_PCI_EXPRESS_ATOMIC_OP SetupAtomicOp; BOOLEAN SetupLtr; UINT8 SetupExtTag; + UINT8 SetupAspm; }; =20 #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c index eaef3d3..5e350e7 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c @@ -1518,3 +1518,394 @@ ProgramExtTag ( return Status; } =20 +/** + Set the ASPM device policy as per the device's link capability. +**/ +UINT8 +SetAspmPolicy ( + IN UINT8 PciExpressLinkCapAspm + ) +{ + switch (PciExpressLinkCapAspm) { + case 0: + // + // cannot support ASPM state, disable + // + return EFI_PCI_EXPRESS_ASPM_DISABLE; + case 1: + // + // supports only ASPM L0s state + // + return EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT; + case 2: + // + // supports only ASPM L1 state + // + return EFI_PCI_EXPRESS_ASPM_L1_SUPPORT; + case 3: + // + // supports both L0s and L1 ASPM states + // + return EFI_PCI_EXPRESS_ASPM_L0S_L1_SUPPORT; + } + return EFI_PCI_EXPRESS_ASPM_DISABLE; +} + +/** + The main routine to setup the PCI Express feature ASPM as per the + device-specific platform policy, as well as in complaince with the PCI E= xpress + Base specification Revision 5. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciExpressConfigurationTable pointer to PCI_EXPRESS_FEATURES_CON= FIGURATION_TABLE + + @retval EFI_SUCCESS setup of PCI feature LTR is succes= sful. +**/ +EFI_STATUS +SetupAspm ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExpressConfigurationTa= ble + ) +{ + PCI_REG_PCIE_LINK_CAPABILITY PciExLinkCap; + PCI_REG_PCIE_DEVICE_CAPABILITY PciExpressDeviceCapability; + BOOLEAN AlignAspmPolicy; + + PciExLinkCap.Uint32 =3D PciDevice->PciExpressCapabilityStructure.LinkCap= ability.Uint32; + PciExpressDeviceCapability.Uint32 =3D PciDevice->PciExpressCapabilityStr= ucture.DeviceCapability.Uint32; + // + // ASPM support is only applicable to root bridge and its child devices.= Not + // applicable to empty bridge devices or RCiEP devices + // + if (PciExpressConfigurationTable) { + PciExpressConfigurationTable->L0sExitLatency =3D MAX ( + PciExpressConfigurationTable->L0sExitLatency, + (UINT8)PciExLinkCap.Bits.L0sExitLatency + ); + PciExpressConfigurationTable->L1ExitLatency =3D MAX ( + PciExpressConfigurationTable->L1ExitLatency, + (UINT8)PciExLinkCap.Bits.L1ExitLatency + ); + if (PciDevice->SetupAspm =3D=3D EFI_PCI_EXPRESS_ASPM_AUTO) { + // + // set the ASPM support as per device's link capability + // + PciDevice->SetupAspm =3D SetAspmPolicy ((UINT8)PciExLinkCap.Bits.Asp= m); + } else { + // + // Check the ASPM device policy is applicable to the link capability. + // In case of invalid device policy, there are 2 options: + // (1) ASPM disable -> platform request rightly denied, and no ASPM + // (2) set as per the device capability -> platform request rightly = denied, + // but still set applicable power management + // this implementation shall take option 2 to overule invalid platfo= rm request + // and go with applicable policy as per device capability + // + switch (SetAspmPolicy ((UINT8)PciExLinkCap.Bits.Aspm)) { + case EFI_PCI_EXPRESS_ASPM_DISABLE: + PciDevice->SetupAspm =3D EFI_PCI_EXPRESS_ASPM_DISABLE; + break; + case EFI_PCI_EXPRESS_ASPM_L1_SUPPORT: + if (PciDevice->SetupAspm =3D=3D EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT= ) { + // + // not applicable, set as per device's link capability + // + PciDevice->SetupAspm =3D EFI_PCI_EXPRESS_ASPM_L1_SUPPORT; + } + break; + case EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT: + if (PciDevice->SetupAspm =3D=3D EFI_PCI_EXPRESS_ASPM_L1_SUPPORT)= { + // + // not applicable, set as per device's link capability + // + PciDevice->SetupAspm =3D EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT; + } + break; + } + } + // + // set the ASPM policy to minimum state among all the devices links + // + PciExpressConfigurationTable->AspmSupport =3D MIN ( + PciExpressConfigurationT= able->AspmSupport, + PciDevice->SetupAspm + ); + // + // check the common ASPM value applicable as per this device capabilit= y, if + // not applicable disable the ASPM for all the devices + // + if ( + (PciExpressConfigurationTable->AspmSupport =3D=3D EFI_PCI_EXPRESS_AS= PM_L0s_SUPPORT + && SetAspmPolicy ((UINT8)PciExLinkCap.Bits.Aspm) =3D=3D EFI_PCI_EX= PRESS_ASPM_L1_SUPPORT) + || + (PciExpressConfigurationTable->AspmSupport =3D=3D EFI_PCI_EXPRESS_AS= PM_L1_SUPPORT + && SetAspmPolicy ((UINT8)PciExLinkCap.Bits.Aspm) =3D=3D EFI_PCI_EX= PRESS_ASPM_L0s_SUPPORT) + ) { + // + // disable the ASPM + // + PciExpressConfigurationTable->AspmSupport =3D EFI_PCI_EXPRESS_ASPM_D= ISABLE; + PciDevice->SetupAspm =3D PciExpressConfigurationTable->AspmSupport; + } + + if (PciExpressConfigurationTable->AspmSupport !=3D EFI_PCI_EXPRESS_ASP= M_DISABLE) { + // + // in case of ASPM policy is not to disable the ASPM support, check = other + // condition of EP device L0s/L1 acceptance latency with the L0s/L1 = exit + // latencies comprising from this endpoint all the way up to root co= mplex + // root port, to determine whether the ASPM L0s/L1 entry can be used= with + // no loss of performance + // + if (!IS_PCI_BRIDGE (&PciDevice->Pci)) { + + switch (PciExpressConfigurationTable->AspmSupport) { + case EFI_PCI_EXPRESS_ASPM_L0S_L1_SUPPORT: + if ( + PciExpressDeviceCapability.Bits.EndpointL0sAcceptableLaten= cy >=3D PciExpressConfigurationTable->L0sExitLatency + && PciExpressDeviceCapability.Bits.EndpointL1AcceptableLat= ency >=3D PciExpressConfigurationTable->L1ExitLatency + ) { + // + // both the L0s & L1 acceptance of this endpoint device is g= reater + // than or equal to all of the comprised L0s & L1 exit laten= cies + // thus good to set the ASPM to L0s & L1 state + // + AlignAspmPolicy =3D TRUE; + } else { + // + // in case the EP device L0s and L1 Acceptance latency does = not match + // with the comprised L0s & L1 exit latencies than disable t= he ASPM + // state + // + AlignAspmPolicy =3D FALSE; + } + break; + + case EFI_PCI_EXPRESS_ASPM_L1_SUPPORT: + if ( + PciExpressDeviceCapability.Bits.EndpointL1AcceptableLatenc= y >=3D PciExpressConfigurationTable->L1ExitLatency + ) { + // + // the endpoint device L1 acceptance latency meets the all t= he + // comprised L1 exit latencies of all the devices from the b= ridge + // hence ASPM L1 is applicable state for the PCI tree + // + AlignAspmPolicy =3D TRUE; + } else { + // + // in case the EP device L1 Acceptance latency does not match + // with the comprised L1 exit latencies than disable the ASPM + // state + // + AlignAspmPolicy =3D FALSE; + } + break; + + case EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT: + if ( + PciExpressDeviceCapability.Bits.EndpointL0sAcceptableLaten= cy >=3D PciExpressConfigurationTable->L0sExitLatency + ) { + // + // the endpoint device L0s acceptance latency meets the all = the + // comprised L0s exit latencies of all the devices from the = bridge + // hence ASPM L0s is applicable state for the PCI tree + // + AlignAspmPolicy =3D TRUE; + } else { + // + // in case the EP device L0s Acceptance latency does not mat= ch + // with the comprised L0s exit latencies than disable the AS= PM + // state + // + AlignAspmPolicy =3D FALSE; + } + break; + } + } else { + // + // align the bridge with the global common ASPM value + // + AlignAspmPolicy =3D TRUE; + } + } else { + // + // ASPM is disabled for all the devices + // + AlignAspmPolicy =3D FALSE; + } + + if (AlignAspmPolicy) { + // + // reset the device's ASPM policy to common minimum value + // + if (PciDevice->SetupAspm !=3D PciExpressConfigurationTable->AspmSupp= ort) { + PciDevice->SetupAspm =3D PciExpressConfigurationTable->AspmSupport; + } + } else { + // + // disable the ASPM + // + PciExpressConfigurationTable->AspmSupport =3D EFI_PCI_EXPRESS_ASPM_D= ISABLE; + PciDevice->SetupAspm =3D PciExpressConfigurationTable->AspmSupport; + } + DEBUG (( + DEBUG_INFO, + "Aspm: %d [cap:%d],", + PciDevice->SetupAspm, + (PciExLinkCap.Bits.Aspm + 1) + )); + } + + return EFI_SUCCESS; +} + +/** + Setup of PCI Express feature ASPM in the PciExpressFeatureEntendedSetupP= hase +**/ +EFI_STATUS +AlignAspm ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExpressConfigurationTa= ble + ) +{ + // + // ASPM support is only applicable to root bridge and its child devices.= Not + // applicable to empty bridge devices or RCiEP devices + // + if (PciExpressConfigurationTable) { + // + // reset the device's ASPM policy to common minimum ASPM value + // + if (PciDevice->SetupAspm !=3D PciExpressConfigurationTable->AspmSuppor= t) { + PciDevice->SetupAspm =3D PciExpressConfigurationTable->AspmSupport; + } + DEBUG (( + DEBUG_INFO, + "Aspm: %d,", + PciDevice->SetupAspm + )); + } + + return EFI_SUCCESS; +} + + +/** + Get the ASPM value from the ASPM device policy. +**/ +UINT8 +GetAspmValue ( + IN UINT8 AspmPolicy + ) +{ + switch (AspmPolicy) { + case EFI_PCI_EXPRESS_ASPM_DISABLE: + // + // ASPM disable + // + return 0; + case EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT: + // + // ASPM L0s state + // + return 1; + case EFI_PCI_EXPRESS_ASPM_L1_SUPPORT: + // + // ASPM L1 state + // + return 2; + case EFI_PCI_EXPRESS_ASPM_L0S_L1_SUPPORT: + // + // L0s and L1 ASPM states + // + return 3; + } + return 0; +} + +/** + Program the PCIe Link Control register ASPM Control field; if + the hardware value is different than the intended value. + + @param PciDevice A pointer to the PCI_IO_DEVICE instance. + + @retval EFI_SUCCESS The data was read from or written to the P= CI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramAspm ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExFeatureConfiguration + ) +{ + PCI_REG_PCIE_LINK_CONTROL LinkCtl; + UINT32 Offset; + EFI_STATUS Status; + EFI_TPL OldTpl; + UINT8 AspmValue; + + // + // ASPM support is only applicable to root bridge and its child devices.= Not + // applicable to empty bridge devices or RCiEP devices + // + if (!PciExFeatureConfiguration) { + return EFI_SUCCESS; + } + + // + // read the link Control register for the ASPM Control + // + LinkCtl.Uint16 =3D 0; + Offset =3D PciDevice->PciExpressCapabilityOffset + + OFFSET_OF (PCI_CAPABILITY_PCIEXP, LinkControl); + Status =3D PciDevice->PciIo.Pci.Read ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &LinkCtl.Uint16 + ); + ASSERT (Status =3D=3D EFI_SUCCESS); + + AspmValue =3D GetAspmValue (PciDevice->SetupAspm); + if (AspmValue !=3D LinkCtl.Bits.AspmControl) { + DEBUG (( + DEBUG_INFO, + "Aspm: %d,", + AspmValue + )); + // + // Raise TPL to high level to disable timer interrupt while the write = operation completes + // + OldTpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + + Status =3D PciDevice->PciIo.Pci.Write ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &LinkCtl.Uint16 + ); + // + // Restore TPL to its original level + // + gBS->RestoreTPL (OldTpl); + + if (!EFI_ERROR (Status)) { + PciDevice->PciExpressCapabilityStructure.LinkControl.Uint16 =3D Link= Ctl.Uint16; + } else { + ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, = PciDevice->FunctionNumber, Offset); + return Status; + } + } else { + DEBUG (( + DEBUG_INFO, + "No Aspm (%d),", + AspmValue + )); + } + return EFI_SUCCESS; +} + diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h index 1cfca54..351c61e 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h @@ -9,6 +9,15 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #ifndef _EFI_PCI_EXPRESS_FEATURES_H_ #define _EFI_PCI_EXPRESS_FEATURES_H_ =20 +// +// PCIe L0s Exit Latencies declarations +// +#define PCIE_LINK_CAPABILITY_L0S_EXIT_LATENCY_64NS 0 // less than 64ns + +// +// PCIe L1 Exit latencies declarations +// +#define PCIE_LINK_CAPABILITY_L1_EXIT_LATENCY_1US 0 // less than 1us =20 /** The main routine which process the PCI feature Max_Payload_Size as per t= he @@ -293,4 +302,47 @@ ProgramExtTag ( IN VOID *PciExFeatureConfiguration ); =20 +/** + The main routine to setup the PCI Express feature ASPM as per the + device-specific platform policy, as well as in complaince with the PCI E= xpress + Base specification Revision 5. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciFeaturesConfigurationTable pointer to PCI_EXPRESS_FEATURES_CO= NFIGURATION_TABLE + + @retval EFI_SUCCESS setup of PCI feature LTR is succes= sful. +**/ +EFI_STATUS +SetupAspm ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciFeaturesConfigurationT= able + ); + +/** + Setup of PCI Express feature ASPM in the PciExpressFeatureEntendedSetupP= hase +**/ +EFI_STATUS +AlignAspm ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciFeaturesConfigurationT= able + ); + +/** + Program the PCIe Link Control register ASPM Control field; if + the hardware value is different than the intended value. + + @param PciDevice A pointer to the PCI_IO_DEVICE instance. + + @retval EFI_SUCCESS The data was read from or written to the P= CI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramAspm ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExFeatureConfiguration + ); + #endif diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c index 58d3780..24781c6 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c @@ -50,7 +50,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY mPciExpressPl= atformPolicy =3D { // // support for PCI Express feature - ASPM state // - FALSE, + TRUE, // // support for PCI Express feature - Common Clock Configuration // @@ -96,6 +96,15 @@ BOOLEAN mPciExpressGetPlatformPolicyComplete =3D FALSE; // PCI_EXPRESS_FEATURE_INITIALIZATION_POINT mPciExpressFeatureInitialization= List[] =3D { =20 + { + PciExpressFeatureSetupPhase, PciExpressAspm, SetupAspm + }, + { + PciExpressFeatureEntendedSetupPhase, PciExpressAspm, AlignAspm + }, + { + PciExpressFeatureProgramPhase, PciExpressAspm, ProgramAspm + }, { PciExpressFeatureSetupPhase, PciExpressMps, SetupMaxPa= yloadSize }, @@ -688,6 +697,18 @@ CreatePciRootBridgeDeviceNode ( // start by assuming the Extended Tag is 10b Requester capable // PciConfigTable->ExtendedTag =3D EFI_PCI_EXPRESS_EXTEND= ED_TAG_10BIT; + // + // initial state set to ASPM L0s and L1 both + // + PciConfigTable->AspmSupport =3D EFI_PCI_EXPRESS_ASPM_L= 0S_L1_SUPPORT; + // + // start by assuming less than 64ns of L0s Exit Latency + // + PciConfigTable->L0sExitLatency =3D PCIE_LINK_CAPABILITY_L= 0S_EXIT_LATENCY_64NS; + // + // start by assuming less than 1us of L1 Exit Latency + // + PciConfigTable->L1ExitLatency =3D PCIE_LINK_CAPABILITY_L= 1_EXIT_LATENCY_1US; } =20 RootBridgeNode->PciExFeaturesConfigurationTable =3D PciConfigTable; diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h index c7cc7e5..5e0f43b 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h @@ -98,6 +98,20 @@ struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE { // to configure a common extended tag size for all the childs of a root = port // UINT8 ExtendedTag; + // + // to configure common ASPM state for all the devices link + // + UINT8 AspmSupport; + // + // to record maximum L0s Exit Latency among all the devices starting fro= m root + // bridge device to its downstream bridge and its endpoint device + // + UINT8 L0sExitLatency; + // + // to record maximum L1 Exit Latency among all the devices starting from= root + // bridge device to its downstream bridge and its endpoint device + // + UINT8 L1ExitLatency; }; =20 // diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c index 98d9875..f301557 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c @@ -374,6 +374,16 @@ SetupDefaultPciExpressDevicePolicy ( PciDevice->SetupExtTag =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; } =20 + // + // default device policy for device's link ASPM + // + if (mPciExpressPlatformPolicy.Aspm) { + PciDevice->SetupAspm =3D EFI_PCI_EXPRESS_ASPM_AUTO; + } else { + PciDevice->SetupAspm =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; + } + + } =20 /** @@ -517,6 +527,14 @@ GetPciExpressDevicePolicy ( PciDevice->SetupExtTag =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; } =20 + // + // set the device-specific policy for the PCI Express feature ASPM + // + if (mPciExpressPlatformPolicy.Aspm) { + PciDevice->SetupAspm =3D PciExpressDevicePolicy.LinkCtlASPMState; + } else { + PciDevice->SetupAspm =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; + } =20 DEBUG (( DEBUG_INFO, @@ -697,6 +715,24 @@ GetPciExpressExtTag ( } } =20 +EFI_PCI_EXPRESS_ASPM_SUPPORT +GetPciExpressAspmState ( + IN PCI_IO_DEVICE *PciDevice + ) +{ + switch (PciDevice->PciExpressCapabilityStructure.LinkControl.Bits.AspmCo= ntrol) { + case 0: + return EFI_PCI_EXPRESS_ASPM_DISABLE; + case 1: + return EFI_PCI_EXPRESS_ASPM_L0s_SUPPORT; + case 2: + return EFI_PCI_EXPRESS_ASPM_L1_SUPPORT; + case 3: + return EFI_PCI_EXPRESS_ASPM_L0S_L1_SUPPORT; + } + return EFI_PCI_EXPRESS_NOT_APPLICABLE; +} + /** Notifies the platform about the current PCI Express state of the device. =20 @@ -805,6 +841,15 @@ PciExpressPlatformNotifyDeviceState ( PciExDeviceConfiguration.DeviceCtlExtTag =3D EFI_PCI_EXPRESS_NOT_APPLI= CABLE; } =20 + // + // get the device-specific state for PCIe ASPM state + // + if (mPciExpressPlatformPolicy.Aspm) { + PciExDeviceConfiguration.LinkCtlASPMState =3D GetPciExpressAspmState (= PciDevice); + } else { + PciExDeviceConfiguration.LinkCtlASPMState =3D EFI_PCI_EXPRESS_NOT_APPL= ICABLE; + } + if (mPciExPlatformProtocol !=3D NULL) { return mPciExPlatformProtocol->NotifyDeviceState ( mPciExPlatformProtocol, --=20 2.21.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#54074): https://edk2.groups.io/g/devel/message/54074 Mute This Topic: https://groups.io/mt/71063093/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri Apr 19 14:36:52 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) client-ip=66.175.222.12; envelope-from=bounce+27952+54075+1787277+3901457@groups.io; helo=web01.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.12 as permitted sender) smtp.mailfrom=bounce+27952+54075+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com Received: from web01.groups.io (web01.groups.io [66.175.222.12]) by mx.zohomail.com with SMTPS id 1581105997745590.0743447701425; Fri, 7 Feb 2020 12:06:37 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id 6HKxYY1788612xMayANv0mvW; Fri, 07 Feb 2020 12:06:37 -0800 X-Received: from mga18.intel.com (mga18.intel.com []) by mx.groups.io with SMTP id smtpd.web09.10529.1581105978095314348 for ; Fri, 07 Feb 2020 12:06:36 -0800 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False X-Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Feb 2020 12:06:35 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,414,1574150400"; d="scan'208";a="225644353" X-Received: from unknown (HELO PIDSBABIOS005.gar.corp.intel.com) ([10.223.9.183]) by fmsmga007.fm.intel.com with ESMTP; 07 Feb 2020 12:06:33 -0800 From: "Javeed, Ashraf" To: devel@edk2.groups.io Cc: Jian J Wang , Hao A Wu , Ray Ni Subject: [edk2-devel] [edk2-staging/UEFI_PCI_ENHANCE-2 PATCH 12/12] PciBusDxe: New PCI Express feature Common CLock Config Date: Sat, 8 Feb 2020 01:34:47 +0530 Message-Id: <20200207200447.10536-13-ashraf.javeed@intel.com> In-Reply-To: <20200207200447.10536-1-ashraf.javeed@intel.com> References: <20200207200447.10536-1-ashraf.javeed@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,ashraf.javeed@intel.com X-Gm-Message-State: QZqfl4GSvfFFuNPNW3uXleH1x1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1581105997; bh=hDhiCpH4ppaC2EZfUj5egwJs78FhH1NtgOGwY7G7imE=; h=Cc:Date:From:Reply-To:Subject:To; b=iN4J1eFSzJfOe8uAfJRFS7AAcaxTtLKNySyNLnErQe2ukqoX19VfRcuyRUOTfkBjHuZ He7XFCPkPp8L1lL+ObSZuqx9kPvJmWEOTF5NVwpaFBXpSckhfv55IQRbl3H7p1JbDJPPM 0LEPBmNoqmR8bgfpCsw998kCn80zJfJhpUg= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2500 This code change enforces the Link Control register CCC field as per the following conditions:- (1) When the Clock Configuration device policy for all the devices are set to EFI_PCI_EXPRESS_CLK_CFG_AUTO:- - Based on the Link Status register's Slot Clock Configuration field, all the devices CCC value shall be aligned (2) When the Clock Configuration device policy for one or more devices are either set to EFI_PCI_EXPRESS_CLK_CFG_ASYNCH or EFI_PCI_EXPRESS_ CLK_CFG_COMMON - enforces the same clock configuration for all the devices from root bridge Note that the recommendation to the platform is to always provide the device policy as EFI_PCI_EXPRESS_CLK_CFG_AUTO. In case for any device its Link Control register CCC field is required to be changed based on its present HW-state, than Link Retraining is preformed on the downstream ports as per the PCI Express Base specification. This programming of CCC, gets the device-specific platform policy using the new PCI Express Platform Protocol interface (ECR version 0.8), defined in the below feature request:- https://bugzilla.tianocore.org/show_bug.cgi?id=3D1954 Signed-off-by: Ashraf Javeed Cc: Jian J Wang Cc: Hao A Wu Cc: Ray Ni --- MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h | 1 + MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c | 267 ++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h | 51 ++++++++++++++++= +++++++++++++++++++++++++++++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c | 20 ++++++++++++++++= ++-- MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h | 9 +++++++++ MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c | 28 ++++++++++++++++= ++++++++++++ 6 files changed, 374 insertions(+), 2 deletions(-) diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/MdeModulePkg/Bus/Pci= /PciBusDxe/PciBus.h index b5caffe..34f482d 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h @@ -299,6 +299,7 @@ struct _PCI_IO_DEVICE { BOOLEAN SetupLtr; UINT8 SetupExtTag; UINT8 SetupAspm; + EFI_PCI_EXPRESS_COMMON_CLOCK_CFG SetupCcc; }; =20 #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c index 5e350e7..1e2f4a4 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c @@ -1909,3 +1909,270 @@ ProgramAspm ( return EFI_SUCCESS; } =20 +/** + The main routine to setup the PCI Express feature Common Clock configura= tion + as per the device-specific platform policy, as well as in complaince wit= h the + PCI Express Base specification Revision 5. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciExpressConfigurationTable pointer to PCI_EXPRESS_FEATURES_CON= FIGURATION_TABLE + + @retval EFI_SUCCESS setup of PCI feature LTR is succes= sful. +**/ +EFI_STATUS +SetupCommonClkCfg ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExpressConfigurationTa= ble + ) +{ + PCI_REG_PCIE_LINK_STATUS LinkSts; + + LinkSts.Uint16 =3D PciDevice->PciExpressCapabilityStructure.LinkStatus.U= int16; + + // + // Common Clock Configuration is only applicable to root bridge and its = child + // devices. Not applicable to empty bridge devices or RCiEP devices + // + if (PciExpressConfigurationTable) { + if (PciDevice->SetupCcc =3D=3D EFI_PCI_EXPRESS_CLK_CFG_AUTO) { + // + // as per the PCI Express Base Specification, the link status regist= er + // slot clock configuration of the opposing side of link devices ind= icate + // the clock configuration properly; hence rely on this data to conf= igure + // the link's clock configuration + // + if (LinkSts.Bits.SlotClockConfiguration) { + PciExpressConfigurationTable->CommonClockConfiguration =3D TRUE; + } else { + PciExpressConfigurationTable->CommonClockConfiguration =3D FALSE; + } + } else if (PciDevice->SetupCcc =3D=3D EFI_PCI_EXPRESS_CLK_CFG_ASYNCH) { + // + // platform override to any device shall change for other device on = the + // link, the clock configuration has to be maintained common across = all + // the devices + // + PciExpressConfigurationTable->CommonClockConfiguration =3D FALSE; + } else { + PciExpressConfigurationTable->CommonClockConfiguration =3D TRUE; + } + } + return EFI_SUCCESS; +} + +/** + Program the PCIe Link Control register Coomon Clock Configuration field;= if + the hardware value is different than the intended value. + + @param PciDevice A pointer to the PCI_IO_DEVICE instance. + + @retval EFI_SUCCESS The data was read from or written to the P= CI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramCcc ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExFeatureConfiguration + ) +{ + PCI_REG_PCIE_LINK_CONTROL LinkCtl; + UINT32 Offset; + EFI_STATUS Status; + EFI_TPL OldTpl; + + // + // Common Clock Configuration is only applicable to root bridge and its = child + // devices. Not applicable to empty bridge devices or RCiEP devices + // + if (!PciExFeatureConfiguration) { + return EFI_SUCCESS; + } + + // + // read the link Control register for the ASPM Control + // + LinkCtl.Uint16 =3D 0; + Offset =3D PciDevice->PciExpressCapabilityOffset + + OFFSET_OF (PCI_CAPABILITY_PCIEXP, LinkControl); + Status =3D PciDevice->PciIo.Pci.Read ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &LinkCtl.Uint16 + ); + ASSERT (Status =3D=3D EFI_SUCCESS); + + // + // in case Common Clock Configuration is required to be programmed in the + // downstream ports from the root bridge devices in the heirarchy + // + if (PciExFeatureConfiguration->CommonClockConfiguration =3D=3D TRUE) { + if (LinkCtl.Bits.CommonClockConfiguration =3D=3D 0) { + LinkCtl.Bits.CommonClockConfiguration =3D 1; + // + // current clock mode does not match hence retrain of the link at br= idge device + // is required + // + PciExFeatureConfiguration->LinkReTrain =3D TRUE; + } + } else { + // + // in case the opposing devices of the PCI link have different referen= ce clock + // set the link control register CCC field accordingly + // + if (LinkCtl.Bits.CommonClockConfiguration) { + LinkCtl.Bits.CommonClockConfiguration =3D 0; + // + // current clock mode does not match hence retrain of the link at br= idge device + // is required + // + PciExFeatureConfiguration->LinkReTrain =3D TRUE; + } + } + // + // use the retrain flag as a sigm to also update the CCC of the link reg= ister + // + if (PciExFeatureConfiguration->LinkReTrain =3D=3D TRUE) { + DEBUG (( + DEBUG_INFO, + "CCC: %d,", + LinkCtl.Bits.CommonClockConfiguration + )); + // + // Raise TPL to high level to disable timer interrupt while the write = operation completes + // + OldTpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + + Status =3D PciDevice->PciIo.Pci.Write ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &LinkCtl.Uint16 + ); + // + // Restore TPL to its original level + // + gBS->RestoreTPL (OldTpl); + + if (!EFI_ERROR (Status)) { + PciDevice->PciExpressCapabilityStructure.LinkControl.Uint16 =3D Link= Ctl.Uint16; + } else { + ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, = PciDevice->FunctionNumber, Offset); + return Status; + } + } else { + PciDevice->PciExpressCapabilityStructure.LinkControl.Uint16 =3D LinkCt= l.Uint16; + DEBUG (( + DEBUG_INFO, + "No CCC (%d),", + LinkCtl.Bits.CommonClockConfiguration + )); + } + return EFI_SUCCESS; +} + +/** + Second phase of programming for Common Clock COnfiguration, conditoonall= y done + only on the downstream ports (bridge devices only). + + @param PciDevice A pointer to the PCI_IO_DEVICE instance. + + @retval EFI_SUCCESS The data was read from or written to the P= CI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +EnforceCcc ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExFeatureConfiguration + ) +{ + PCI_REG_PCIE_LINK_CONTROL LinkCtl; + PCI_REG_PCIE_LINK_STATUS LinkSts; + PCI_REG_PCIE_CAPABILITY PciExCap; + UINT32 Offset; + EFI_STATUS Status; + EFI_TPL OldTpl; + + // + // Common Clock Configuration is only applicable to root bridge and its = child + // devices. Not applicable to empty bridge devices or RCiEP devices + // + if (!PciExFeatureConfiguration) { + return EFI_SUCCESS; + } + PciExCap.Uint16 =3D PciDevice->PciExpressCapabilityStructure.Capability.= Uint16; + LinkCtl.Uint16 =3D PciDevice->PciExpressCapabilityStructure.LinkControl.= Uint16; + + // + // retrain the bridge device (downstream ports including the root port) + // + if (PciExFeatureConfiguration->LinkReTrain =3D=3D TRUE) { + if (IS_PCI_BRIDGE (&PciDevice->Pci)) { + // + // retrain of the PCI link happens for CCC change only on the downst= ream + // ports + // + if ( + PciExCap.Bits.DevicePortType =3D=3D PCIE_DEVICE_PORT_TYPE_ROOT_PORT + || PciExCap.Bits.DevicePortType =3D=3D PCIE_DEVICE_PORT_TYPE_DOWNS= TREAM_PORT + ) { + LinkCtl.Bits.RetrainLink =3D 1; + Offset =3D PciDevice->PciExpressCapabilityOffset + + OFFSET_OF (PCI_CAPABILITY_PCIEXP, LinkControl); + // + // Raise TPL to high level to disable timer interrupt while the wr= ite operation completes + // + OldTpl =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); + + Status =3D PciDevice->PciIo.Pci.Write ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &LinkCtl.Uint16 + ); + // + // Restore TPL to its original level + // + gBS->RestoreTPL (OldTpl); + + if (!EFI_ERROR (Status)) { + // + // poll the link status register for the link retrain to be comp= lete + // + Offset =3D PciDevice->PciExpressCapabilityOffset + + OFFSET_OF (PCI_CAPABILITY_PCIEXP, LinkStatu= s); + do { + Status =3D PciDevice->PciIo.Pci.Read ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &LinkSts.Uint16 + ); + ASSERT (Status =3D=3D EFI_SUCCESS); + } while (LinkSts.Bits.LinkTraining); + } else { + ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumb= er, PciDevice->FunctionNumber, Offset); + return Status; + } + } + // + // ignore the upstream bridge devices + // + } + // + // not applicable to endpoint devices + // + } + return EFI_SUCCESS; +} + diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h index 351c61e..33df337 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h @@ -345,4 +345,55 @@ ProgramAspm ( IN VOID *PciExFeatureConfiguration ); =20 +/** + The main routine to setup the PCI Express feature Common Clock configura= tion + as per the device-specific platform policy, as well as in complaince wit= h the + PCI Express Base specification Revision 5. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciExpressConfigurationTable pointer to PCI_EXPRESS_FEATURES_CON= FIGURATION_TABLE + + @retval EFI_SUCCESS setup of PCI feature LTR is succes= sful. +**/ +EFI_STATUS +SetupCommonClkCfg ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExpressConfigurationTa= ble + ); + +/** + Program the PCIe Link Control register Coomon Clock Configuration field;= if + the hardware value is different than the intended value. + + @param PciDevice A pointer to the PCI_IO_DEVICE instance. + + @retval EFI_SUCCESS The data was read from or written to the P= CI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramCcc ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExFeatureConfiguration + ); + +/** + Second phase of programming for Common Clock COnfiguration, conditoonall= y done + only on the downstream ports (bridge devices only). + + @param PciDevice A pointer to the PCI_IO_DEVICE instance. + + @retval EFI_SUCCESS The data was read from or written to the P= CI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Wid= th, and Count is not + valid for the PCI configuration header of = the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +EnforceCcc ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExFeatureConfiguration + ); #endif diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c index 24781c6..4d3641c 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c @@ -54,7 +54,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY mPciExpressPl= atformPolicy =3D { // // support for PCI Express feature - Common Clock Configuration // - FALSE, + TRUE, // // support for PCI Express feature - Extended Sync // @@ -95,7 +95,15 @@ BOOLEAN mPciExpressGetPlatformPolicyComplete =3D FALSE; // PCI Express feature initialization phase handle routines // PCI_EXPRESS_FEATURE_INITIALIZATION_POINT mPciExpressFeatureInitialization= List[] =3D { - + { + PciExpressFeatureSetupPhase, PciExpressCcc, SetupCommo= nClkCfg + }, + { + PciExpressFeatureEntendedSetupPhase, PciExpressCcc, ProgramCcc + }, + { + PciExpressFeatureProgramPhase, PciExpressCcc, EnforceCcc + }, { PciExpressFeatureSetupPhase, PciExpressAspm, SetupAspm }, @@ -709,6 +717,14 @@ CreatePciRootBridgeDeviceNode ( // start by assuming less than 1us of L1 Exit Latency // PciConfigTable->L1ExitLatency =3D PCIE_LINK_CAPABILITY_L= 1_EXIT_LATENCY_1US; + // + // default link retrain is not required + // + PciConfigTable->LinkReTrain =3D FALSE; + // + // start by assuming no common clock configuration mode for the device= 's link + // + PciConfigTable->CommonClockConfiguration =3D FALSE; } =20 RootBridgeNode->PciExFeaturesConfigurationTable =3D PciConfigTable; diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModule= Pkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h index 5e0f43b..481bd90 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h @@ -112,6 +112,15 @@ struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE { // bridge device to its downstream bridge and its endpoint device // UINT8 L1ExitLatency; + // + // flag to indicate the link training is required in the devices of down= stream + // ports + // + BOOLEAN LinkReTrain; + // + // link status slot clock configuration + // + BOOLEAN CommonClockConfiguration; }; =20 // diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModul= ePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c index f301557..bf380ab 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c @@ -383,6 +383,14 @@ SetupDefaultPciExpressDevicePolicy ( PciDevice->SetupAspm =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; } =20 + // + // default device policy for the device's link clock configuration + // + if (mPciExpressPlatformPolicy.Ccc) { + PciDevice->SetupCcc =3D EFI_PCI_EXPRESS_CLK_CFG_AUTO; + } else { + PciDevice->SetupCcc =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; + } =20 } =20 @@ -536,6 +544,15 @@ GetPciExpressDevicePolicy ( PciDevice->SetupAspm =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; } =20 + // + // set the device policy for the PCI Express feature Common Clock Conf= iguration + // + if (mPciExpressPlatformPolicy.Ccc) { + PciDevice->SetupCcc =3D PciExpressDevicePolicy.LinkCtlCommonClkCfg; + } else { + PciDevice->SetupCcc =3D EFI_PCI_EXPRESS_NOT_APPLICABLE; + } + DEBUG (( DEBUG_INFO, "[device policy: platform]" @@ -850,6 +867,17 @@ PciExpressPlatformNotifyDeviceState ( PciExDeviceConfiguration.LinkCtlASPMState =3D EFI_PCI_EXPRESS_NOT_APPL= ICABLE; } =20 + // + // get the device-specific Common CLock Configuration value + // + if (mPciExpressPlatformPolicy.Ccc) { + PciExDeviceConfiguration.LinkCtlCommonClkCfg =3D + PciDevice->PciExpressCapabilityStructure.LinkControl.Bits.CommonCl= ockConfiguration ? + EFI_PCI_EXPRESS_CLK_CFG_COMMON : EFI_PCI_EXPRESS_CLK_CFG_ASYNC= H; + } else { + PciExDeviceConfiguration.LinkCtlCommonClkCfg =3D EFI_PCI_EXPRESS_NOT_A= PPLICABLE; + } + if (mPciExPlatformProtocol !=3D NULL) { return mPciExPlatformProtocol->NotifyDeviceState ( mPciExPlatformProtocol, --=20 2.21.0.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#54075): https://edk2.groups.io/g/devel/message/54075 Mute This Topic: https://groups.io/mt/71063097/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-