summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2017-11-29 01:43:50 +0300
committerBjorn Helgaas <bhelgaas@google.com>2017-12-19 08:02:56 +0300
commitc46fd358070f22ba68d6e74c22016a33b914c20a (patch)
tree484d136f67cb8243a6790c1578a7497561b71311
parent80d7d7a904fac3f8114448dbb8cc9fa253b10120 (diff)
downloadlinux-c46fd358070f22ba68d6e74c22016a33b914c20a.tar.xz
PCI/ASPM: Enable Latency Tolerance Reporting when supported
Enable Latency Tolerance Reporting (LTR). Note that LTR must be enabled in the Root Port first, and must not be enabled in any downstream device unless the Root Port and all intermediate Switches also support LTR. See PCIe r3.1, sec 6.18. Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Vidya Sagar <vidyas@nvidia.com>
-rw-r--r--drivers/pci/probe.c33
-rw-r--r--include/linux/pci.h2
2 files changed, 35 insertions, 0 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 14e0ea1ff38b..3761b1303529 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1875,6 +1875,38 @@ static void pci_configure_relaxed_ordering(struct pci_dev *dev)
}
}
+static void pci_configure_ltr(struct pci_dev *dev)
+{
+#ifdef CONFIG_PCIEASPM
+ u32 cap;
+ struct pci_dev *bridge;
+
+ if (!pci_is_pcie(dev))
+ return;
+
+ pcie_capability_read_dword(dev, PCI_EXP_DEVCAP2, &cap);
+ if (!(cap & PCI_EXP_DEVCAP2_LTR))
+ return;
+
+ /*
+ * Software must not enable LTR in an Endpoint unless the Root
+ * Complex and all intermediate Switches indicate support for LTR.
+ * PCIe r3.1, sec 6.18.
+ */
+ if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
+ dev->ltr_path = 1;
+ else {
+ bridge = pci_upstream_bridge(dev);
+ if (bridge && bridge->ltr_path)
+ dev->ltr_path = 1;
+ }
+
+ if (dev->ltr_path)
+ pcie_capability_set_word(dev, PCI_EXP_DEVCTL2,
+ PCI_EXP_DEVCTL2_LTR_EN);
+#endif
+}
+
static void pci_configure_device(struct pci_dev *dev)
{
struct hotplug_params hpp;
@@ -1883,6 +1915,7 @@ static void pci_configure_device(struct pci_dev *dev)
pci_configure_mps(dev);
pci_configure_extended_tags(dev, NULL);
pci_configure_relaxed_ordering(dev);
+ pci_configure_ltr(dev);
memset(&hpp, 0, sizeof(hpp));
ret = pci_get_hp_params(dev, &hpp);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index c170c9250c8b..d75d30e55976 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -350,6 +350,8 @@ struct pci_dev {
#ifdef CONFIG_PCIEASPM
struct pcie_link_state *link_state; /* ASPM link state */
+ unsigned int ltr_path:1; /* Latency Tolerance Reporting
+ supported from root to here */
#endif
pci_channel_state_t error_state; /* current connectivity state */