From: Bjorn Helgaas <bhelg...@google.com>

[ Upstream commit 7b38fd9760f51cc83d80eed2cfbde8b5ead9e93a ]

Except for Endpoints, we enable PTM at enumeration-time.  Previously we did
not account for the fact that Switch Downstream Ports are not permitted to
have a PTM capability; their PTM behavior is controlled by the Upstream
Port (PCIe r5.0, sec 7.9.16).  Since Downstream Ports don't have a PTM
capability, we did not mark them as "ptm_enabled", which meant that
pci_enable_ptm() on an Endpoint failed because there was no PTM path to it.

Mark Downstream Ports as "ptm_enabled" if their Upstream Port has PTM
enabled.

Fixes: eec097d43100 ("PCI: Add pci_enable_ptm() for drivers to enable PTM on 
endpoints")
Reported-by: Aditya Paluri <venkata.adityapal...@synopsys.com>
Signed-off-by: Bjorn Helgaas <bhelg...@google.com>
Signed-off-by: Sasha Levin <sas...@kernel.org>
---
 drivers/pci/pcie/ptm.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/pci/pcie/ptm.c b/drivers/pci/pcie/ptm.c
index 9361f3aa26ab8..357a454cafa07 100644
--- a/drivers/pci/pcie/ptm.c
+++ b/drivers/pci/pcie/ptm.c
@@ -39,10 +39,6 @@ void pci_ptm_init(struct pci_dev *dev)
        if (!pci_is_pcie(dev))
                return;
 
-       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_PTM);
-       if (!pos)
-               return;
-
        /*
         * Enable PTM only on interior devices (root ports, switch ports,
         * etc.) on the assumption that it causes no link traffic until an
@@ -52,6 +48,23 @@ void pci_ptm_init(struct pci_dev *dev)
             pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END))
                return;
 
+       /*
+        * Switch Downstream Ports are not permitted to have a PTM
+        * capability; their PTM behavior is controlled by the Upstream
+        * Port (PCIe r5.0, sec 7.9.16).
+        */
+       ups = pci_upstream_bridge(dev);
+       if (pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM &&
+           ups && ups->ptm_enabled) {
+               dev->ptm_granularity = ups->ptm_granularity;
+               dev->ptm_enabled = 1;
+               return;
+       }
+
+       pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_PTM);
+       if (!pos)
+               return;
+
        pci_read_config_dword(dev, pos + PCI_PTM_CAP, &cap);
        local_clock = (cap & PCI_PTM_GRANULARITY_MASK) >> 8;
 
@@ -61,7 +74,6 @@ void pci_ptm_init(struct pci_dev *dev)
         * the spec recommendation (PCIe r3.1, sec 7.32.3), select the
         * furthest upstream Time Source as the PTM Root.
         */
-       ups = pci_upstream_bridge(dev);
        if (ups && ups->ptm_enabled) {
                ctrl = PCI_PTM_CTRL_ENABLE;
                if (ups->ptm_granularity == 0)
-- 
2.25.1



Reply via email to