| From ed54263988f13a0842bfb641def4e7151f1029ef Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 21 May 2020 15:40:07 -0500 |
| Subject: PCI/PTM: Inherit Switch Downstream Port PTM settings from Upstream |
| Port |
| |
| From: Bjorn Helgaas <bhelgaas@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.AdityaPaluri@synopsys.com> |
| Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> |
| Signed-off-by: Sasha Levin <sashal@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 3008bba360f35..ec6f6213960b4 100644 |
| --- a/drivers/pci/pcie/ptm.c |
| +++ b/drivers/pci/pcie/ptm.c |
| @@ -47,10 +47,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 |
| @@ -60,6 +56,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; |
| |
| @@ -69,7 +82,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 |
| |