From mboxrd@z Thu Jan 1 00:00:00 1970 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 Authentication-Results: mx.groups.io; dkim=missing; spf=fail (domain: intel.com, ip: , mailfrom: ashraf.javeed@intel.com) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False 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" 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-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> X-Mailer: git-send-email 2.21.0.windows.1 In-Reply-To: <20200207200447.10536-1-ashraf.javeed@intel.com> References: <20200207200447.10536-1-ashraf.javeed@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2499 This code change enables the PCI Express feature LTR, in compliance with the PCI Express Base Specification 5, as well as in accordance its device policy, as follows: (1) all the devices capability register needs to indicate that LTR mecha- nism is supported. ANy device not capable shall lead to all devices state in LTR disable (2) if device policy of any device requests LTR mechanism enabled, than based on above condition (1) is TRUE, all of the devices from root bridge are enabled. (3) Even in case of RCiEP device without any root bridge device; if device policy requests LTR enabled and device capability does not support LTR shall enforce the default LTR disabled state for that device This programming of LTR, gets the device-specific platform policy using the new PCI Express Platform Protocol interface (ECR version 0.8), defined in the below feature request:- https://bugzilla.tianocore.org/show_bug.cgi?id=1954 Signed-off-by: Ashraf Javeed 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; }; #define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c index 5c76ba4..63a243b 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c @@ -1069,3 +1069,174 @@ ProgramAtomicOp ( return Status; } +/** + The main routine which process the PCI feature LTR enable/disable as per the + device-specific platform policy, as well as in complaince with the PCI Express + Base specification Revision 5. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciExpressConfigurationTable pointer to PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE + + @retval EFI_SUCCESS setup of PCI feature LTR is successful. +**/ +EFI_STATUS +SetupLtr ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExpressConfigurationTable + ) +{ + PCI_REG_PCIE_DEVICE_CAPABILITY2 DeviceCap2; + // + // as per the PCI-Express Base Specification, in order to enable LTR mechanism + // in the upstream ports, all the upstream ports and its downstream ports has + // to support the LTR mechanism reported in its Device Capability 2 register + // + DeviceCap2.Uint32 = PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Uint32; + + if (PciExpressConfigurationTable) { + // + // in this phase establish 2 requirements: + // (1) all the PCI devices in the hierarchy supports the LTR mechanism + // (2) check and record any device-specific platform policy that wants to + // enable the LTR mechanism + // + if (!PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Bits.LtrMechanism) { + + // + // it starts with the assumption that all the PCI devices support LTR mechanism + // and negates the flag if any PCI device Device Capability 2 register advertizes + // as not supported + // + PciExpressConfigurationTable->LtrSupported = FALSE; + } + + if (PciDevice->SetupLtr == TRUE) { + // + // it starts with the assumption that device-specific platform policy would + // be set to LTR disable, and negates the flag if any PCI device platform + // policy wants to override to enable the LTR mechanism + // + PciExpressConfigurationTable->LtrEnable = TRUE; + } + } else { + // + // in case of RCiEP device or the bridge device with out any child device, + // overrule the device policy if the device in not capable + // + if (!PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Bits.LtrMechanism + && PciDevice->SetupLtr == TRUE) { + PciDevice->SetupLtr = FALSE; + } + // + // for any bridge device which is Hot-Plug capable, it is expected that platform + // will not enforce the enabling of LTR mechanism only for the bridge device + // + } + + DEBUG (( DEBUG_INFO, "LTR En: %d (LTR Cap: %d),", + PciDevice->SetupLtr ? 1 : 0, + PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Bits.LtrMechanism + )); + return EFI_SUCCESS; +} + +EFI_STATUS +ReSetupLtr ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciExpressConfigurationTable + ) +{ + // + // not applicable to RCiEP device... + // for the bridge device without any child device, the policy is already overruled + // based on capability in the above routine + // + if (PciExpressConfigurationTable) { + // + // in this phase align the device policy to enable LTR policy of any PCI device + // in the tree if all the devices are capable to support the LTR mechanism + // + if (PciExpressConfigurationTable->LtrSupported == TRUE + && PciExpressConfigurationTable->LtrEnable == TRUE + ) { + PciDevice->SetupLtr = TRUE; + } else { + PciDevice->SetupLtr = FALSE; + } + } + + DEBUG (( DEBUG_INFO, "LTR En: %d (LTR Cap: %d),", + PciDevice->SetupLtr ? 1 : 0, + PciDevice->PciExpressCapabilityStructure.DeviceCapability2.Bits.LtrMechanism + )); + return EFI_SUCCESS; +} + +/** + Program the PCI Device Control 2 register LTR mechanism field; if + the hardware value is different than the intended value. + + @param PciDevice A pointer to the PCI_IO_DEVICE instance. + + @retval EFI_SUCCESS The data was read from or written to the PCI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not + valid for the PCI configuration header of the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramLtr ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExFeatureConfiguration + ) +{ + PCI_REG_PCIE_DEVICE_CONTROL2 PcieDev; + UINT32 Offset; + EFI_STATUS Status; + EFI_TPL OldTpl; + + PcieDev.Uint16 = 0; + Offset = PciDevice->PciExpressCapabilityOffset + + OFFSET_OF (PCI_CAPABILITY_PCIEXP, DeviceControl2); + Status = PciDevice->PciIo.Pci.Read ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &PcieDev.Uint16 + ); + ASSERT (Status == EFI_SUCCESS); + + if (PciDevice->SetupLtr != (BOOLEAN) PcieDev.Bits.LtrMechanism) { + PcieDev.Bits.LtrMechanism = PciDevice->SetupLtr ? 1 : 0; + DEBUG (( DEBUG_INFO, "LTR=%d,", PcieDev.Bits.LtrMechanism)); + + // + // Raise TPL to high level to disable timer interrupt while the write operation completes + // + OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + + Status = PciDevice->PciIo.Pci.Write ( + &PciDevice->PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &PcieDev.Uint16 + ); + // + // Restore TPL to its original level + // + gBS->RestoreTPL (OldTpl); + + if (!EFI_ERROR(Status)) { + PciDevice->PciExpressCapabilityStructure.DeviceControl2.Uint16 = PcieDev.Uint16; + } else { + ReportPciWriteError (PciDevice->BusNumber, PciDevice->DeviceNumber, PciDevice->FunctionNumber, Offset); + } + } else { + DEBUG (( DEBUG_INFO, "no LTR,")); + } + + return Status; +} + diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h index 1e287fc..374fe49 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h @@ -203,4 +203,44 @@ ProgramAtomicOp ( IN VOID *PciExFeatureConfiguration ); +/** + The main routine which process the PCI feature LTR enable/disable as per the + device-specific platform policy, as well as in complaince with the PCI Express + Base specification Revision 5. + + @param PciDevice A pointer to the PCI_IO_DEVICE. + @param PciFeaturesConfigurationTable pointer to PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE + + @retval EFI_SUCCESS setup of PCI feature LTR is successful. +**/ +EFI_STATUS +SetupLtr ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciFeaturesConfigurationTable + ); + +EFI_STATUS +ReSetupLtr ( + IN PCI_IO_DEVICE *PciDevice, + IN PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE *PciFeaturesConfigurationTable + ); + +/** + Program the PCI Device Control 2 register LTR mechanism field; if + the hardware value is different than the intended value. + + @param PciDevice A pointer to the PCI_IO_DEVICE instance. + + @retval EFI_SUCCESS The data was read from or written to the PCI device. + @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not + valid for the PCI configuration header of the PCI controller. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +EFI_STATUS +ProgramLtr ( + IN PCI_IO_DEVICE *PciDevice, + IN VOID *PciExFeatureConfiguration + ); + #endif diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c index 9d624a0..bdeb0d2 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c @@ -66,7 +66,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY mPciExpressPlatformPolicy = { // // support for PCI Express feature - LTR // - FALSE, + TRUE, // // support for PCI Express feature - PTM // @@ -131,6 +131,15 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT mPciExpressFeatureInitializationList[] }, { PciExpressFeatureProgramPhase, PciExpressAtomicOp, ProgramAtomicOp + }, + { + PciExpressFeatureSetupPhase, PciExpressLtr, SetupLtr + }, + { + PciExpressFeatureEntendedSetupPhase, PciExpressLtr, ReSetupLtr + }, + { + PciExpressFeatureProgramPhase, PciExpressLtr, ProgramLtr } }; @@ -654,6 +663,14 @@ CreatePciRootBridgeDeviceNode ( // PciConfigTable->Lock_Max_Read_Request_Size = FALSE; // + // start by assuming the LTR mechanism is supported in a PCI tree + // + PciConfigTable->LtrSupported = TRUE; + // + // the default LTR mechanism is disabled as per the PCI Base specification + // + PciConfigTable->LtrEnable = FALSE; + // // start by assuming the AtomicOp Routing capability is supported in the PCI // tree // diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h index 2bd565e..5dded7c 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h @@ -81,6 +81,15 @@ struct _PCI_EXPRESS_FEATURES_CONFIGURATION_TABLE { // BOOLEAN Lock_Max_Read_Request_Size; // + // to record the adversity in LTR mechanism support capability among the PCI + // device of an heirarchy + // + BOOLEAN LtrSupported; + // + // to enable the LTR mechansim for the entire PCI tree from a root port + // + BOOLEAN LtrEnable; + // // to record the AtomicOp Routing capability of the PCI Heirarchy to enable // the AtomicOp of the EP device // diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c index 2707976..83b3aa7 100644 --- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c +++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c @@ -307,6 +307,36 @@ SetDevicePolicyPciExpressCto ( } } +/** + Routine to set the device-specific policy for the PCI feature LTR enable/disable + + @param AtomicOp value corresponding to data type EFI_PCI_EXPRESS_ATOMIC_OP + @param PciDevice A pointer to PCI_IO_DEVICE + +**/ +VOID +SetDevicePolicyPciExpressLtr ( + IN EFI_PCI_EXPRESS_LTR Ltr, + OUT PCI_IO_DEVICE *PciDevice + ) +{ + switch (Ltr){ + case EFI_PCI_EXPRESS_LTR_AUTO: + case EFI_PCI_EXPRESS_LTR_DISABLE: + // + // leave the LTR mechanism disable or restore to its default state + // + PciDevice->SetupLtr = FALSE; + break; + case EFI_PCI_EXPRESS_LTR_ENABLE: + // + // LTR mechanism enable + // + PciDevice->SetupLtr = TRUE; + break; + } +} + /** Generic routine to setup the PCI features as per its predetermined defaults. **/ @@ -336,6 +366,8 @@ SetupDefaultPciExpressDevicePolicy ( PciDevice->SetupAtomicOp.Override = 0; + PciDevice->SetupLtr = FALSE; + } /** @@ -461,6 +493,16 @@ GetPciExpressDevicePolicy ( PciDevice->SetupAtomicOp.Override = 0; } + // + // set the device-specific policy for LTR mechanism in the function + // + if (mPciExpressPlatformPolicy.Ltr) { + SetDevicePolicyPciExpressLtr (PciExpressDevicePolicy.DeviceCtl2LTR, PciDevice); + } else { + PciDevice->SetupLtr = FALSE; + } + + DEBUG (( DEBUG_INFO, "[device policy: platform]" @@ -715,6 +757,17 @@ PciExpressPlatformNotifyDeviceState ( PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpRequester = 0; PciExDeviceConfiguration.DeviceCtl2AtomicOp.Enable_AtomicOpEgressBlocking = 0; } + // + // get the device-specific state for LTR mechanism in the function + // + if (mPciExpressPlatformPolicy.Ltr) { + PciExDeviceConfiguration.DeviceCtl2LTR = PciDevice->PciExpressCapabilityStructure.DeviceControl2.Bits.LtrMechanism + ? EFI_PCI_EXPRESS_LTR_ENABLE + : EFI_PCI_EXPRESS_LTR_DISABLE; + } else { + PciExDeviceConfiguration.DeviceCtl2LTR = EFI_PCI_EXPRESS_NOT_APPLICABLE; + } + if (mPciExPlatformProtocol != NULL) { return mPciExPlatformProtocol->NotifyDeviceState ( -- 2.21.0.windows.1