Skip to content

Commit

Permalink
PciBusDxe: New PCI Express feature LTR
Browse files Browse the repository at this point in the history
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 <ashraf.javeed@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
  • Loading branch information
ashrafj committed Feb 7, 2020
1 parent 176fccc commit fd03852
Show file tree
Hide file tree
Showing 6 changed files with 292 additions and 1 deletion.
1 change: 1 addition & 0 deletions MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
Expand Down
171 changes: 171 additions & 0 deletions MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

40 changes: 40 additions & 0 deletions MdeModulePkg/Bus/Pci/PciBusDxe/PciExpressFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
19 changes: 18 additions & 1 deletion MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ EFI_PCI_EXPRESS_PLATFORM_POLICY mPciExpressPlatformPolicy = {
//
// support for PCI Express feature - LTR
//
FALSE,
TRUE,
//
// support for PCI Express feature - PTM
//
Expand Down Expand Up @@ -131,6 +131,15 @@ PCI_EXPRESS_FEATURE_INITIALIZATION_POINT mPciExpressFeatureInitializationList[]
},
{
PciExpressFeatureProgramPhase, PciExpressAtomicOp, ProgramAtomicOp
},
{
PciExpressFeatureSetupPhase, PciExpressLtr, SetupLtr
},
{
PciExpressFeatureEntendedSetupPhase, PciExpressLtr, ReSetupLtr
},
{
PciExpressFeatureProgramPhase, PciExpressLtr, ProgramLtr
}
};

Expand Down Expand Up @@ -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
//
Expand Down
9 changes: 9 additions & 0 deletions MdeModulePkg/Bus/Pci/PciBusDxe/PciFeatureSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
//
Expand Down
53 changes: 53 additions & 0 deletions MdeModulePkg/Bus/Pci/PciBusDxe/PciPlatformSupport.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
**/
Expand Down Expand Up @@ -336,6 +366,8 @@ SetupDefaultPciExpressDevicePolicy (

PciDevice->SetupAtomicOp.Override = 0;

PciDevice->SetupLtr = FALSE;

}

/**
Expand Down Expand Up @@ -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]"
Expand Down Expand Up @@ -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 (
Expand Down

0 comments on commit fd03852

Please sign in to comment.