Skip to content

Commit 044b9f1

Browse files
westeribjorn-helgaas
authored andcommitted
PCI/PTM: Enable only if device advertises relevant role
We have a Switch Upstream Port (2b:00.0) that has a PTM Capability, but doesn't advertise support for any PTM roles: Capabilities: [220 v1] Precision Time Measurement PTMCap: Requester- Responder- Root- Linux enables PTM without looking into what roles it actually supports, and apparently the Port immediately sends PTM Requests even though it doesn't support the PTM Requester role. The messages include an invalid bus number, so the Root Port detects an ACS Violation (see the PCIe r7.0, sec 6.12.1.1, implementation note): pci 0000:2b:00.0: [8086:5786] type 01 class 0x060400 PCIe Switch Upstream Port pci 0000:2b:00.0: PTM enabled, 4ns granularity pcieport 0000:00:07.1: AER: Multiple Uncorrectable (Non-Fatal) error message received from 0000:00:07.1 pcieport 0000:00:07.1: PCIe Bus Error: severity=Uncorrectable (Non-Fatal), type=Transaction Layer, (Receiver ID) pcieport 0000:00:07.1: device [8086:e44f] error status/mask=00200000/00000000 pcieport 0000:00:07.1: [21] ACSViol (First) pcieport 0000:00:07.1: AER: TLP Header: 0x34000000 0x00000052 0x00000000 0x00000000 The TLP Header shows a 4 DW header, no data (001b) Msg with Local routing (1 0100b) with Requester ID 0x0000 and PTM Request code (0x52). Fix this by enabling PTM only if the following conditions are true (see sec 6.21.1 figure 6-21): - Endpoint must advertise PTM Requester Capable - Switch Upstream Port must advertise PTM Responder Capable - Root Port must advertise PTM Root Capable Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> [bhelgaas: commit log, comments] Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Link: https://patch.msgid.link/20251112074614.1440266-1-mika.westerberg@linux.intel.com
1 parent 3a86608 commit 044b9f1

2 files changed

Lines changed: 25 additions & 0 deletions

File tree

drivers/pci/pcie/ptm.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ void pci_ptm_init(struct pci_dev *dev)
8181
dev->ptm_granularity = 0;
8282
}
8383

84+
if (cap & PCI_PTM_CAP_RES)
85+
dev->ptm_responder = 1;
86+
if (cap & PCI_PTM_CAP_REQ)
87+
dev->ptm_requester = 1;
88+
8489
if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT ||
8590
pci_pcie_type(dev) == PCI_EXP_TYPE_UPSTREAM)
8691
pci_enable_ptm(dev, NULL);
@@ -144,6 +149,24 @@ static int __pci_enable_ptm(struct pci_dev *dev)
144149
return -EINVAL;
145150
}
146151

152+
switch (pci_pcie_type(dev)) {
153+
case PCI_EXP_TYPE_ROOT_PORT:
154+
if (!dev->ptm_root)
155+
return -EINVAL;
156+
break;
157+
case PCI_EXP_TYPE_UPSTREAM:
158+
if (!dev->ptm_responder)
159+
return -EINVAL;
160+
break;
161+
case PCI_EXP_TYPE_ENDPOINT:
162+
case PCI_EXP_TYPE_LEG_END:
163+
if (!dev->ptm_requester)
164+
return -EINVAL;
165+
break;
166+
default:
167+
return -EINVAL;
168+
}
169+
147170
pci_read_config_dword(dev, ptm + PCI_PTM_CTRL, &ctrl);
148171

149172
ctrl |= PCI_PTM_CTRL_ENABLE;

include/linux/pci.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,8 @@ struct pci_dev {
500500
#ifdef CONFIG_PCIE_PTM
501501
u16 ptm_cap; /* PTM Capability */
502502
unsigned int ptm_root:1;
503+
unsigned int ptm_responder:1;
504+
unsigned int ptm_requester:1;
503505
unsigned int ptm_enabled:1;
504506
u8 ptm_granularity;
505507
#endif

0 commit comments

Comments
 (0)