]> Gentwo Git Trees - linux/.git/commitdiff
PCI/PTM: Enable only if device advertises relevant role
authorMika Westerberg <mika.westerberg@linux.intel.com>
Wed, 12 Nov 2025 07:46:14 +0000 (08:46 +0100)
committerBjorn Helgaas <bhelgaas@google.com>
Wed, 12 Nov 2025 23:11:15 +0000 (17:11 -0600)
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
drivers/pci/pcie/ptm.c
include/linux/pci.h

index 65e4b008be00df46e96a70419ed0f29d415e2e6f..ed0f9691e7d16e6a47928c14b81a137d12503d0c 100644 (file)
@@ -81,6 +81,11 @@ void pci_ptm_init(struct pci_dev *dev)
                dev->ptm_granularity = 0;
        }
 
+       if (cap & PCI_PTM_CAP_RES)
+               dev->ptm_responder = 1;
+       if (cap & PCI_PTM_CAP_REQ)
+               dev->ptm_requester = 1;
+
        if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT ||
            pci_pcie_type(dev) == PCI_EXP_TYPE_UPSTREAM)
                pci_enable_ptm(dev, NULL);
@@ -144,6 +149,24 @@ static int __pci_enable_ptm(struct pci_dev *dev)
                        return -EINVAL;
        }
 
+       switch (pci_pcie_type(dev)) {
+       case PCI_EXP_TYPE_ROOT_PORT:
+               if (!dev->ptm_root)
+                       return -EINVAL;
+               break;
+       case PCI_EXP_TYPE_UPSTREAM:
+               if (!dev->ptm_responder)
+                       return -EINVAL;
+               break;
+       case PCI_EXP_TYPE_ENDPOINT:
+       case PCI_EXP_TYPE_LEG_END:
+               if (!dev->ptm_requester)
+                       return -EINVAL;
+               break;
+       default:
+               return -EINVAL;
+       }
+
        pci_read_config_dword(dev, ptm + PCI_PTM_CTRL, &ctrl);
 
        ctrl |= PCI_PTM_CTRL_ENABLE;
index d1fdf81fbe1e427aecbc951fa3fdf65c20450b05..d5018cb5c331563bd9c1051485af98eca05d6db0 100644 (file)
@@ -500,6 +500,8 @@ struct pci_dev {
 #ifdef CONFIG_PCIE_PTM
        u16             ptm_cap;                /* PTM Capability */
        unsigned int    ptm_root:1;
+       unsigned int    ptm_responder:1;
+       unsigned int    ptm_requester:1;
        unsigned int    ptm_enabled:1;
        u8              ptm_granularity;
 #endif