Introduce enum tph_req_policy to support auto, standard (8-bit ST) and extended (16-bit ST) TPH requester selection. Extend pcie_enable_tph() to take the new policy argument, implement selection logic and add strict input validation. Update function prototype, inline fallback stub and kernel-doc to reflect new parameters and behavior. Refresh Documentation/PCI/tph.rst to document the updated function signature and new requester policy options. Adapt existing call sites in bnxt and mlx5 drivers to use TPH_REQ_AUTO to preserve original runtime behavior. Signed-off-by: Chengwen Feng --- Documentation/PCI/tph.rst | 12 ++++++-- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +- .../net/ethernet/mellanox/mlx5/core/lib/st.c | 2 +- drivers/pci/tph.c | 29 +++++++++++++++---- include/linux/pci-tph.h | 16 ++++++++-- 5 files changed, 49 insertions(+), 12 deletions(-) diff --git a/Documentation/PCI/tph.rst b/Documentation/PCI/tph.rst index b6cf22b9bd90..112630db756a 100644 --- a/Documentation/PCI/tph.rst +++ b/Documentation/PCI/tph.rst @@ -47,15 +47,23 @@ Manage TPH To enable TPH for a device, use the following function:: - int pcie_enable_tph(struct pci_dev *pdev, int mode); + int pcie_enable_tph(struct pci_dev *pdev, int mode, + enum tph_req_policy req_policy); This function enables TPH support for device with a specific ST mode. -Current supported modes include: + +Supported modes include: * PCI_TPH_ST_NS_MODE - NO ST Mode * PCI_TPH_ST_IV_MODE - Interrupt Vector Mode * PCI_TPH_ST_DS_MODE - Device Specific Mode +Supported requester policies: + + * TPH_REQ_AUTO - Auto select by hardware/root port capability + * TPH_REQ_STANDARD - Force standard TPH (8-bit Steering Tag) + * TPH_REQ_EXTENDED - Force extended TPH (16-bit Steering Tag) + `pcie_enable_tph()` checks whether the requested mode is actually supported by the device before enabling. The device driver can figure out which TPH mode is supported and can be properly enabled based on the diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 008c34cff7b4..1f8d3e728a9f 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -11846,7 +11846,7 @@ static int bnxt_request_irq(struct bnxt *bp) #endif /* Enable TPH support as part of IRQ request */ - rc = pcie_enable_tph(bp->pdev, PCI_TPH_ST_IV_MODE); + rc = pcie_enable_tph(bp->pdev, PCI_TPH_ST_IV_MODE, TPH_REQ_AUTO); if (!rc) bp->tph_mode = PCI_TPH_ST_IV_MODE; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/st.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/st.c index 997be91f0a13..26ce59d16785 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/st.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/st.c @@ -55,7 +55,7 @@ struct mlx5_st *mlx5_st_create(struct mlx5_core_dev *dev) } /* The OS doesn't support ST */ - ret = pcie_enable_tph(pdev, PCI_TPH_ST_DS_MODE); + ret = pcie_enable_tph(pdev, PCI_TPH_ST_DS_MODE, TPH_REQ_AUTO); if (ret) return NULL; diff --git a/drivers/pci/tph.c b/drivers/pci/tph.c index b4ecc510033a..04ff051ebed3 100644 --- a/drivers/pci/tph.c +++ b/drivers/pci/tph.c @@ -373,14 +373,21 @@ EXPORT_SYMBOL(pcie_disable_tph); * - PCI_TPH_ST_IV_MODE: Interrupt Vector Mode * - PCI_TPH_ST_DS_MODE: Device Specific Mode * + * @req_policy: TPH requester selection policy + * + * - TPH_REQ_AUTO: Auto select by hardware/root port capability + * - TPH_REQ_STANDARD: Force standard TPH (8-bit ST) + * - TPH_REQ_EXTENDED: Force extended TPH (16-bit ST) + * * Check whether the mode is actually supported by the device before enabling - * and return an error if not. Additionally determine what types of requests, - * TPH or extended TPH, can be issued by the device based on its TPH requester - * capability and the Root Port's completer capability. + * and return an error if not. Select TPH requester type according to + * @req_policy and negotiated capability between device and root port. Return + * error for invalid policy or unsupported extended TPH requests. * * Return: 0 on success, otherwise negative value (-errno) */ -int pcie_enable_tph(struct pci_dev *pdev, int mode) +int pcie_enable_tph(struct pci_dev *pdev, int mode, + enum tph_req_policy req_policy) { u32 reg; u8 dev_modes; @@ -403,8 +410,18 @@ int pcie_enable_tph(struct pci_dev *pdev, int mode) pdev->tph_mode = mode; - pdev->tph_req_type = pdev->tph_ext_requester ? PCI_TPH_REQ_EXT_TPH : - PCI_TPH_REQ_TPH_ONLY; + if (req_policy == TPH_REQ_AUTO) { + pdev->tph_req_type = pdev->tph_ext_requester ? + PCI_TPH_REQ_EXT_TPH : PCI_TPH_REQ_TPH_ONLY; + } else if (req_policy == TPH_REQ_STANDARD) { + pdev->tph_req_type = PCI_TPH_REQ_TPH_ONLY; + } else if (req_policy == TPH_REQ_EXTENDED) { + if (!pdev->tph_ext_requester) + return -EINVAL; + pdev->tph_req_type = PCI_TPH_REQ_EXT_TPH; + } else { + return -EINVAL; + } /* Write them into TPH control register */ pci_read_config_dword(pdev, pdev->tph_cap + PCI_TPH_CTRL, ®); diff --git a/include/linux/pci-tph.h b/include/linux/pci-tph.h index 7502fef81833..8a9c45b1e907 100644 --- a/include/linux/pci-tph.h +++ b/include/linux/pci-tph.h @@ -20,6 +20,16 @@ enum tph_mem_type { TPH_MEM_TYPE_PM /* persistent memory */ }; +/* + * TPH requester selection policy + * Used to choose standard/extended TPH when enabling TPH + */ +enum tph_req_policy { + TPH_REQ_AUTO, /* Kernel auto selection based on capability */ + TPH_REQ_STANDARD, /* Force standard TPH (8-bit ST) */ + TPH_REQ_EXTENDED /* Force extended TPH (16-bit ST) */ +}; + #ifdef CONFIG_PCIE_TPH int pcie_tph_set_st_entry(struct pci_dev *pdev, unsigned int index, u16 tag); @@ -27,7 +37,8 @@ int pcie_tph_get_cpu_st(struct pci_dev *dev, enum tph_mem_type mem_type, unsigned int cpu, u16 *tag); void pcie_disable_tph(struct pci_dev *pdev); -int pcie_enable_tph(struct pci_dev *pdev, int mode); +int pcie_enable_tph(struct pci_dev *pdev, int mode, + enum tph_req_policy req_policy); u16 pcie_tph_get_st_table_size(struct pci_dev *pdev); u32 pcie_tph_get_st_table_loc(struct pci_dev *pdev); #else @@ -39,7 +50,8 @@ static inline int pcie_tph_get_cpu_st(struct pci_dev *dev, unsigned int cpu, u16 *tag) { return -EINVAL; } static inline void pcie_disable_tph(struct pci_dev *pdev) { } -static inline int pcie_enable_tph(struct pci_dev *pdev, int mode) +static inline int pcie_enable_tph(struct pci_dev *pdev, int mode, + enum tph_req_policy req_policy) { return -EINVAL; } static inline u16 pcie_tph_get_st_table_size(struct pci_dev *pdev) { return 0; } -- 2.17.1