Merge branch 'pci/ptm'

- Leave Precision Time Measurement disabled until a driver enables it to
  avoid PCIe errors (Mika Westerberg)

* pci/ptm:
  PCI/PTM: Do not enable PTM automatically for Root and Switch Upstream Ports
  PCI/PTM: Drop pci_enable_ptm() granularity parameter
This commit is contained in:
Bjorn Helgaas
2026-04-13 12:50:04 -05:00
6 changed files with 48 additions and 43 deletions
+1 -1
View File
@@ -5028,7 +5028,7 @@ static int ice_init(struct ice_pf *pf)
}
if (pf->hw.mac_type == ICE_MAC_E830) {
err = pci_enable_ptm(pf->pdev, NULL);
err = pci_enable_ptm(pf->pdev);
if (err)
dev_dbg(dev, "PCIe PTM not supported by PCIe bus/controller\n");
}
+1 -1
View File
@@ -257,7 +257,7 @@ static int idpf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_free;
}
err = pci_enable_ptm(pdev, NULL);
err = pci_enable_ptm(pdev);
if (err)
pci_dbg(pdev, "PCIe PTM is not supported by PCIe bus/controller\n");
+1 -1
View File
@@ -7123,7 +7123,7 @@ static int igc_probe(struct pci_dev *pdev,
if (err)
goto err_pci_reg;
err = pci_enable_ptm(pdev, NULL);
err = pci_enable_ptm(pdev);
if (err < 0)
dev_info(&pdev->dev, "PCIe PTM not supported by PCIe bus/controller\n");
@@ -960,7 +960,7 @@ static int mlx5_pci_init(struct mlx5_core_dev *dev, struct pci_dev *pdev,
mlx5_pci_vsc_init(dev);
pci_enable_ptm(pdev, NULL);
pci_enable_ptm(pdev);
return 0;
+41 -36
View File
@@ -52,6 +52,7 @@ void pci_ptm_init(struct pci_dev *dev)
return;
dev->ptm_cap = ptm;
atomic_set(&dev->ptm_enable_cnt, 0);
pci_add_ext_cap_save_buffer(dev, PCI_EXT_CAP_ID_PTM, sizeof(u32));
pci_read_config_dword(dev, ptm + PCI_PTM_CAP, &cap);
@@ -85,10 +86,6 @@ void pci_ptm_init(struct pci_dev *dev)
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);
}
void pci_save_ptm_state(struct pci_dev *dev)
@@ -129,26 +126,11 @@ void pci_restore_ptm_state(struct pci_dev *dev)
static int __pci_enable_ptm(struct pci_dev *dev)
{
u16 ptm = dev->ptm_cap;
struct pci_dev *ups;
u32 ctrl;
if (!ptm)
return -EINVAL;
/*
* A device uses local PTM Messages to request time information
* from a PTM Root that's farther upstream. Every device along the
* path must support PTM and have it enabled so it can handle the
* messages. Therefore, if this device is not a PTM Root, the
* upstream link partner must have PTM enabled before we can enable
* PTM.
*/
if (!dev->ptm_root) {
ups = pci_upstream_ptm(dev);
if (!ups || !ups->ptm_enabled)
return -EINVAL;
}
switch (pci_pcie_type(dev)) {
case PCI_EXP_TYPE_ROOT_PORT:
if (!dev->ptm_root)
@@ -182,27 +164,46 @@ static int __pci_enable_ptm(struct pci_dev *dev)
/**
* pci_enable_ptm() - Enable Precision Time Measurement
* @dev: PCI device
* @granularity: pointer to return granularity
*
* Enable Precision Time Measurement for @dev. If successful and
* @granularity is non-NULL, return the Effective Granularity.
* Enable Precision Time Measurement for @dev.
*
* Return: zero if successful, or -EINVAL if @dev lacks a PTM Capability or
* is not a PTM Root and lacks an upstream path of PTM-enabled devices.
*/
int pci_enable_ptm(struct pci_dev *dev, u8 *granularity)
int pci_enable_ptm(struct pci_dev *dev)
{
int rc;
char clock_desc[8];
/*
* A device uses local PTM Messages to request time information
* from a PTM Root that's farther upstream. Every device along
* the path must support PTM and have it enabled so it can
* handle the messages. Therefore, if this device is not a PTM
* Root, the upstream link partner must have PTM enabled before
* we can enable PTM.
*/
if (!dev->ptm_root) {
struct pci_dev *parent;
parent = pci_upstream_ptm(dev);
if (!parent)
return -EINVAL;
/* Enable PTM for the parent */
rc = pci_enable_ptm(parent);
if (rc)
return rc;
}
/* Already enabled? */
if (atomic_inc_return(&dev->ptm_enable_cnt) > 1)
return 0;
rc = __pci_enable_ptm(dev);
if (rc)
if (rc) {
atomic_dec(&dev->ptm_enable_cnt);
return rc;
dev->ptm_enabled = 1;
if (granularity)
*granularity = dev->ptm_granularity;
}
switch (dev->ptm_granularity) {
case 0:
@@ -244,27 +245,31 @@ static void __pci_disable_ptm(struct pci_dev *dev)
*/
void pci_disable_ptm(struct pci_dev *dev)
{
if (dev->ptm_enabled) {
struct pci_dev *parent;
if (atomic_dec_and_test(&dev->ptm_enable_cnt))
__pci_disable_ptm(dev);
dev->ptm_enabled = 0;
}
parent = pci_upstream_ptm(dev);
if (parent)
pci_disable_ptm(parent);
}
EXPORT_SYMBOL(pci_disable_ptm);
/*
* Disable PTM, but preserve dev->ptm_enabled so we silently re-enable it on
* Disable PTM, but preserve dev->ptm_enable_cnt so we silently re-enable it on
* resume if necessary.
*/
void pci_suspend_ptm(struct pci_dev *dev)
{
if (dev->ptm_enabled)
if (atomic_read(&dev->ptm_enable_cnt))
__pci_disable_ptm(dev);
}
/* If PTM was enabled before suspend, re-enable it when resuming */
void pci_resume_ptm(struct pci_dev *dev)
{
if (dev->ptm_enabled)
if (atomic_read(&dev->ptm_enable_cnt))
__pci_enable_ptm(dev);
}
@@ -273,7 +278,7 @@ bool pcie_ptm_enabled(struct pci_dev *dev)
if (!dev)
return false;
return dev->ptm_enabled;
return atomic_read(&dev->ptm_enable_cnt);
}
EXPORT_SYMBOL(pcie_ptm_enabled);
+3 -3
View File
@@ -518,7 +518,7 @@ struct pci_dev {
unsigned int ptm_root:1;
unsigned int ptm_responder:1;
unsigned int ptm_requester:1;
unsigned int ptm_enabled:1;
atomic_t ptm_enable_cnt;
u8 ptm_granularity;
#endif
#ifdef CONFIG_PCI_MSI
@@ -1973,11 +1973,11 @@ struct pci_ptm_debugfs {
};
#ifdef CONFIG_PCIE_PTM
int pci_enable_ptm(struct pci_dev *dev, u8 *granularity);
int pci_enable_ptm(struct pci_dev *dev);
void pci_disable_ptm(struct pci_dev *dev);
bool pcie_ptm_enabled(struct pci_dev *dev);
#else
static inline int pci_enable_ptm(struct pci_dev *dev, u8 *granularity)
static inline int pci_enable_ptm(struct pci_dev *dev)
{ return -EINVAL; }
static inline void pci_disable_ptm(struct pci_dev *dev) { }
static inline bool pcie_ptm_enabled(struct pci_dev *dev)