PCI: Disable PCIe Relaxed Ordering if unsupported
When bit4 is set in the PCIe Device Control register, it indicates whether the device is permitted to use relaxed ordering. On some platforms using relaxed ordering can have performance issues or due to erratum can cause data-corruption. In such cases devices must avoid using relaxed ordering. The patch adds a new flag PCI_DEV_FLAGS_NO_RELAXED_ORDERING to indicate that Relaxed Ordering (RO) attribute should not be used for Transaction Layer Packets (TLP) targeted towards these affected root complexes. This patch checks if there is any node in the hierarchy that indicates that using relaxed ordering is not safe. In such cases the patch turns off the relaxed ordering by clearing the capability for this device. Signed-off-by: Casey Leedom <leedom@chelsio.com> Signed-off-by: Ding Tianhong <dingtianhong@huawei.com> Acked-by: Ashok Raj <ashok.raj@intel.com> Acked-by: Alexander Duyck <alexander.h.duyck@intel.com> Acked-by: Casey Leedom <leedom@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
59a361bc6f
commit
a99b646afa
@@ -1762,6 +1762,48 @@ static void pci_configure_extended_tags(struct pci_dev *dev)
|
||||
PCI_EXP_DEVCTL_EXT_TAG);
|
||||
}
|
||||
|
||||
/**
|
||||
* pcie_relaxed_ordering_enabled - Probe for PCIe relaxed ordering enable
|
||||
* @dev: PCI device to query
|
||||
*
|
||||
* Returns true if the device has enabled relaxed ordering attribute.
|
||||
*/
|
||||
bool pcie_relaxed_ordering_enabled(struct pci_dev *dev)
|
||||
{
|
||||
u16 v;
|
||||
|
||||
pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &v);
|
||||
|
||||
return !!(v & PCI_EXP_DEVCTL_RELAX_EN);
|
||||
}
|
||||
EXPORT_SYMBOL(pcie_relaxed_ordering_enabled);
|
||||
|
||||
static void pci_configure_relaxed_ordering(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_dev *root;
|
||||
|
||||
/* PCI_EXP_DEVICE_RELAX_EN is RsvdP in VFs */
|
||||
if (dev->is_virtfn)
|
||||
return;
|
||||
|
||||
if (!pcie_relaxed_ordering_enabled(dev))
|
||||
return;
|
||||
|
||||
/*
|
||||
* For now, we only deal with Relaxed Ordering issues with Root
|
||||
* Ports. Peer-to-Peer DMA is another can of worms.
|
||||
*/
|
||||
root = pci_find_pcie_root_port(dev);
|
||||
if (!root)
|
||||
return;
|
||||
|
||||
if (root->dev_flags & PCI_DEV_FLAGS_NO_RELAXED_ORDERING) {
|
||||
pcie_capability_clear_word(dev, PCI_EXP_DEVCTL,
|
||||
PCI_EXP_DEVCTL_RELAX_EN);
|
||||
dev_info(&dev->dev, "Disable Relaxed Ordering because the Root Port didn't support it\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void pci_configure_device(struct pci_dev *dev)
|
||||
{
|
||||
struct hotplug_params hpp;
|
||||
@@ -1769,6 +1811,7 @@ static void pci_configure_device(struct pci_dev *dev)
|
||||
|
||||
pci_configure_mps(dev);
|
||||
pci_configure_extended_tags(dev);
|
||||
pci_configure_relaxed_ordering(dev);
|
||||
|
||||
memset(&hpp, 0, sizeof(hpp));
|
||||
ret = pci_get_hp_params(dev, &hpp);
|
||||
|
Reference in New Issue
Block a user