diff options
| author | Bjorn Helgaas <bhelgaas@google.com> | 2026-04-13 12:50:04 -0500 |
|---|---|---|
| committer | Bjorn Helgaas <bhelgaas@google.com> | 2026-04-13 12:50:04 -0500 |
| commit | 7d7c6ebd46d952335ff33e21f77fdd761ac2b573 (patch) | |
| tree | 2f268aeab9141687a0c8d23838828ea6b153ad66 | |
| parent | a735a513ff2c219f3dc4f9c159f3a328bfb41834 (diff) | |
| parent | e1092d5e15e6a9b168bf830af9a26d7ea17cd57d (diff) | |
| download | lwn-7d7c6ebd46d952335ff33e21f77fdd761ac2b573.tar.gz lwn-7d7c6ebd46d952335ff33e21f77fdd761ac2b573.zip | |
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
| -rw-r--r-- | drivers/net/ethernet/intel/ice/ice_main.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/idpf/idpf_main.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igc/igc_main.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/main.c | 2 | ||||
| -rw-r--r-- | drivers/pci/pcie/ptm.c | 77 | ||||
| -rw-r--r-- | include/linux/pci.h | 6 |
6 files changed, 48 insertions, 43 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index ebf48feffb30..b35c4e4ecd2a 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -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"); } diff --git a/drivers/net/ethernet/intel/idpf/idpf_main.c b/drivers/net/ethernet/intel/idpf/idpf_main.c index 0dd741dcfcdb..ab3c409e587b 100644 --- a/drivers/net/ethernet/intel/idpf/idpf_main.c +++ b/drivers/net/ethernet/intel/idpf/idpf_main.c @@ -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"); diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 27e5c2109138..b030acf94ac4 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -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"); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index fdc3ba20912e..0b94d4ed0ef6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -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; diff --git a/drivers/pci/pcie/ptm.c b/drivers/pci/pcie/ptm.c index 91a598ed534c..a41ffd1914de 100644 --- a/drivers/pci/pcie/ptm.c +++ b/drivers/pci/pcie/ptm.c @@ -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]; - rc = __pci_enable_ptm(dev); - if (rc) - return rc; + /* + * 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; + } - dev->ptm_enabled = 1; + /* Already enabled? */ + if (atomic_inc_return(&dev->ptm_enable_cnt) > 1) + return 0; - if (granularity) - *granularity = dev->ptm_granularity; + rc = __pci_enable_ptm(dev); + if (rc) { + atomic_dec(&dev->ptm_enable_cnt); + return rc; + } 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); diff --git a/include/linux/pci.h b/include/linux/pci.h index 482dd8460dd9..47c5b0c09ffb 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -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) |
