Skip to content

Commit a99b646

Browse files
dingtianhongdavem330
authored andcommitted
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 <[email protected]> Signed-off-by: Ding Tianhong <[email protected]> Acked-by: Ashok Raj <[email protected]> Acked-by: Alexander Duyck <[email protected]> Acked-by: Casey Leedom <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 59a361b commit a99b646

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

drivers/pci/probe.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,13 +1762,56 @@ static void pci_configure_extended_tags(struct pci_dev *dev)
17621762
PCI_EXP_DEVCTL_EXT_TAG);
17631763
}
17641764

1765+
/**
1766+
* pcie_relaxed_ordering_enabled - Probe for PCIe relaxed ordering enable
1767+
* @dev: PCI device to query
1768+
*
1769+
* Returns true if the device has enabled relaxed ordering attribute.
1770+
*/
1771+
bool pcie_relaxed_ordering_enabled(struct pci_dev *dev)
1772+
{
1773+
u16 v;
1774+
1775+
pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &v);
1776+
1777+
return !!(v & PCI_EXP_DEVCTL_RELAX_EN);
1778+
}
1779+
EXPORT_SYMBOL(pcie_relaxed_ordering_enabled);
1780+
1781+
static void pci_configure_relaxed_ordering(struct pci_dev *dev)
1782+
{
1783+
struct pci_dev *root;
1784+
1785+
/* PCI_EXP_DEVICE_RELAX_EN is RsvdP in VFs */
1786+
if (dev->is_virtfn)
1787+
return;
1788+
1789+
if (!pcie_relaxed_ordering_enabled(dev))
1790+
return;
1791+
1792+
/*
1793+
* For now, we only deal with Relaxed Ordering issues with Root
1794+
* Ports. Peer-to-Peer DMA is another can of worms.
1795+
*/
1796+
root = pci_find_pcie_root_port(dev);
1797+
if (!root)
1798+
return;
1799+
1800+
if (root->dev_flags & PCI_DEV_FLAGS_NO_RELAXED_ORDERING) {
1801+
pcie_capability_clear_word(dev, PCI_EXP_DEVCTL,
1802+
PCI_EXP_DEVCTL_RELAX_EN);
1803+
dev_info(&dev->dev, "Disable Relaxed Ordering because the Root Port didn't support it\n");
1804+
}
1805+
}
1806+
17651807
static void pci_configure_device(struct pci_dev *dev)
17661808
{
17671809
struct hotplug_params hpp;
17681810
int ret;
17691811

17701812
pci_configure_mps(dev);
17711813
pci_configure_extended_tags(dev);
1814+
pci_configure_relaxed_ordering(dev);
17721815

17731816
memset(&hpp, 0, sizeof(hpp));
17741817
ret = pci_get_hp_params(dev, &hpp);

drivers/pci/quirks.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4015,6 +4015,17 @@ DECLARE_PCI_FIXUP_CLASS_EARLY(0x1797, 0x6868, PCI_CLASS_NOT_DEFINED, 8,
40154015
DECLARE_PCI_FIXUP_CLASS_EARLY(0x1797, 0x6869, PCI_CLASS_NOT_DEFINED, 8,
40164016
quirk_tw686x_class);
40174017

4018+
/*
4019+
* Some devices have problems with Transaction Layer Packets with the Relaxed
4020+
* Ordering Attribute set. Such devices should mark themselves and other
4021+
* Device Drivers should check before sending TLPs with RO set.
4022+
*/
4023+
static void quirk_relaxedordering_disable(struct pci_dev *dev)
4024+
{
4025+
dev->dev_flags |= PCI_DEV_FLAGS_NO_RELAXED_ORDERING;
4026+
dev_info(&dev->dev, "Disable Relaxed Ordering Attributes to avoid PCIe Completion erratum\n");
4027+
}
4028+
40184029
/*
40194030
* Per PCIe r3.0, sec 2.2.9, "Completion headers must supply the same
40204031
* values for the Attribute as were supplied in the header of the

include/linux/pci.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ enum pci_dev_flags {
188188
* the direct_complete optimization.
189189
*/
190190
PCI_DEV_FLAGS_NEEDS_RESUME = (__force pci_dev_flags_t) (1 << 11),
191+
/* Don't use Relaxed Ordering for TLPs directed at this device */
192+
PCI_DEV_FLAGS_NO_RELAXED_ORDERING = (__force pci_dev_flags_t) (1 << 12),
191193
};
192194

193195
enum pci_irq_reroute_variant {
@@ -1125,6 +1127,7 @@ bool pci_check_pme_status(struct pci_dev *dev);
11251127
void pci_pme_wakeup_bus(struct pci_bus *bus);
11261128
void pci_d3cold_enable(struct pci_dev *dev);
11271129
void pci_d3cold_disable(struct pci_dev *dev);
1130+
bool pcie_relaxed_ordering_enabled(struct pci_dev *dev);
11281131

11291132
/* PCI Virtual Channel */
11301133
int pci_save_vc_state(struct pci_dev *dev);

0 commit comments

Comments
 (0)