[PATCH v2] net/cpfl: add timesync support
Mandal, Anurag
anurag.mandal at intel.com
Mon Aug 17 11:18:16 CEST 2026
Hi All,
Gentle reminder for review & ack.
Thank you.
Regards,
Anurag M
> -----Original Message-----
> From: Mandal, Anurag <anurag.mandal at intel.com>
> Sent: 03 August 2026 15:00
> To: dev at dpdk.org
> Cc: Richardson, Bruce <bruce.richardson at intel.com>; Shetty, Praveen
> <praveen.shetty at intel.com>; Mandal, Anurag <anurag.mandal at intel.com>
> Subject: [PATCH v2] net/cpfl: add timesync support
>
> The cpfl PMD advertises RTE_ETH_RX_OFFLOAD_TIMESTAMP, so received
> packets carry a 32-bit hardware timestamp that the common idpf Rx path
> extends to 64-bit nanoseconds using the device PTP clock (PHC).
> However, it never initialised the PHC, so the timestamp conversion had no
> reference time.
> Applications had no way to enable timestamping or to read the current device
> clock to correlate the mbuf timestamps.
>
> This patch adds PTP support by reusing the idpf common PTP helpers:
>
> - timesync_enable: allocate and initialise the adapter PTP state,
> query the PTP capabilities, program the base increment value
> and set the device clock to the current system time.
> The PTP state is shared by all vports of an adapter, so it
> is initialised only once.
>
> - timesync_read_time: return the current device clock as a timespec.
>
> - timesync_disable: release the PTP state.
>
> Once timesync is enabled, the common Rx path resolves the cached PHC time,
> so the mbuf Rx timestamp dynfield reports valid nanosecond values and
> applications can read the device clock with rte_eth_timesync_read_time().
>
> Signed-off-by: Anurag Mandal <anurag.mandal at intel.com>
> ---
> V2: Removed read_clock support
>
> drivers/net/intel/cpfl/cpfl_ethdev.c | 107 +++++++++++++++++++++++++++
> drivers/net/intel/cpfl/cpfl_ethdev.h | 1 +
> drivers/net/intel/idpf/idpf_ptp.c | 5 ++
> drivers/net/intel/idpf/idpf_ptp.h | 4 +
> 4 files changed, 117 insertions(+)
>
> diff --git a/drivers/net/intel/cpfl/cpfl_ethdev.c
> b/drivers/net/intel/cpfl/cpfl_ethdev.c
> index 4315adb68c..e4dabd8043 100644
> --- a/drivers/net/intel/cpfl/cpfl_ethdev.c
> +++ b/drivers/net/intel/cpfl/cpfl_ethdev.c
> @@ -1335,6 +1335,110 @@ cpfl_hairpin_unbind(struct rte_eth_dev *dev,
> uint16_t rx_port)
> return 0;
> }
>
> +static int
> +cpfl_timesync_enable(struct rte_eth_dev *dev) {
> + struct cpfl_vport *cpfl_vport = dev->data->dev_private;
> + struct idpf_vport *vport = &cpfl_vport->base;
> + struct idpf_adapter *adapter = vport->adapter;
> + struct timespec sys_ts;
> + uint64_t ns;
> + int ret;
> +
> + if (dev->data->dev_started && !(dev->data-
> >dev_conf.rxmode.offloads &
> + RTE_ETH_RX_OFFLOAD_TIMESTAMP)) {
> + PMD_DRV_LOG(ERR, "Rx timestamp offload not configured");
> + return -1;
> + }
> +
> + /* PTP state is shared by all vports of the adapter. */
> + if (adapter->ptp != NULL)
> + return 0;
> +
> + adapter->ptp = rte_zmalloc(NULL, sizeof(struct idpf_ptp), 0);
> + if (adapter->ptp == NULL) {
> + PMD_DRV_LOG(ERR, "Failed to allocate memory for PTP");
> + return -ENOMEM;
> + }
> +
> + ret = idpf_ptp_get_caps(adapter);
> + if (ret) {
> + PMD_DRV_LOG(ERR, "Failed to get PTP capabilities, err=%d",
> ret);
> + goto fail_ptp;
> + }
> +
> + /*
> + * Write the default increment time value if the clock adjustments
> + * are enabled.
> + */
> + if (adapter->ptp->adj_dev_clk_time_access != IDPF_PTP_NONE) {
> + ret = idpf_ptp_adj_dev_clk_fine(adapter, adapter->ptp-
> >base_incval);
> + if (ret) {
> + PMD_DRV_LOG(ERR, "PTP set incval failed, err=%d",
> ret);
> + goto fail_ptp;
> + }
> + }
> +
> + /* Do not initialize the PTP if the device clock time cannot be read. */
> + if (adapter->ptp->get_dev_clk_time_access == IDPF_PTP_NONE) {
> + PMD_DRV_LOG(ERR, "Getting device clock time is not
> supported");
> + ret = -EIO;
> + goto fail_ptp;
> + }
> +
> + /* Set the device clock time to system time. */
> + if (adapter->ptp->set_dev_clk_time_access != IDPF_PTP_NONE) {
> + clock_gettime(CLOCK_REALTIME, &sys_ts);
> + ns = rte_timespec_to_ns(&sys_ts);
> + ret = idpf_ptp_set_dev_clk_time(adapter, ns);
> + if (ret) {
> + PMD_DRV_LOG(ERR, "PTP set clock time failed,
> err=%d", ret);
> + goto fail_ptp;
> + }
> + }
> +
> + adapter->ptp->cmd.shtime_enable_mask =
> PF_GLTSYN_CMD_SYNC_SHTIME_EN_M;
> + adapter->ptp->cmd.exec_cmd_mask =
> PF_GLTSYN_CMD_SYNC_EXEC_CMD_M;
> +
> + return 0;
> +
> +fail_ptp:
> + rte_free(adapter->ptp);
> + adapter->ptp = NULL;
> + return ret;
> +}
> +
> +static int
> +cpfl_timesync_read_time(struct rte_eth_dev *dev, struct timespec *ts) {
> + struct cpfl_vport *cpfl_vport = dev->data->dev_private;
> + struct idpf_adapter *adapter = cpfl_vport->base.adapter;
> + uint64_t time;
> + int ret;
> +
> + ret = idpf_ptp_read_src_clk_reg(adapter, &time);
> + if (ret)
> + PMD_DRV_LOG(ERR, "PTP read time failed, err %d", ret);
> + else
> + *ts = rte_ns_to_timespec(time);
> +
> + return ret;
> +}
> +
> +static int
> +cpfl_timesync_disable(struct rte_eth_dev *dev) {
> + struct cpfl_vport *cpfl_vport = dev->data->dev_private;
> + struct idpf_adapter *adapter = cpfl_vport->base.adapter;
> +
> + if (adapter->ptp != NULL) {
> + rte_free(adapter->ptp);
> + adapter->ptp = NULL;
> + }
> +
> + return 0;
> +}
> +
> static const struct eth_dev_ops cpfl_eth_dev_ops = {
> .dev_configure = cpfl_dev_configure,
> .dev_close = cpfl_dev_close,
> @@ -1368,6 +1472,9 @@ static const struct eth_dev_ops cpfl_eth_dev_ops =
> {
> .hairpin_get_peer_ports = cpfl_hairpin_get_peer_ports,
> .hairpin_bind = cpfl_hairpin_bind,
> .hairpin_unbind = cpfl_hairpin_unbind,
> + .timesync_enable = cpfl_timesync_enable,
> + .timesync_read_time = cpfl_timesync_read_time,
> + .timesync_disable = cpfl_timesync_disable,
> };
>
> static int
> diff --git a/drivers/net/intel/cpfl/cpfl_ethdev.h
> b/drivers/net/intel/cpfl/cpfl_ethdev.h
> index d41aa93191..a9e532a46c 100644
> --- a/drivers/net/intel/cpfl/cpfl_ethdev.h
> +++ b/drivers/net/intel/cpfl/cpfl_ethdev.h
> @@ -16,6 +16,7 @@
>
> #include <idpf_common_device.h>
> #include <idpf_common_virtchnl.h>
> +#include <idpf_ptp.h>
> #include <base/idpf_prototype.h>
> #include <base/virtchnl2.h>
>
> diff --git a/drivers/net/intel/idpf/idpf_ptp.c
> b/drivers/net/intel/idpf/idpf_ptp.c
> index 5c3fcb90e4..47830de239 100644
> --- a/drivers/net/intel/idpf/idpf_ptp.c
> +++ b/drivers/net/intel/idpf/idpf_ptp.c
> @@ -2,6 +2,7 @@
> * Copyright(c) 2025 Intel Corporation
> */
>
> +#include <eal_export.h>
> #include "idpf_ptp.h"
> #include "idpf_common_virtchnl.h"
> #include "base/virtchnl2.h"
> @@ -38,6 +39,7 @@ idpf_ptp_get_features_access(const struct idpf_adapter
> *adapter)
> IDPF_PTP_ACCESS(adapter,
> VIRTCHNL2_CAP_PTP_TX_TSTAMPS); }
>
> +RTE_EXPORT_INTERNAL_SYMBOL(idpf_ptp_get_caps)
> int
> idpf_ptp_get_caps(struct idpf_adapter *adapter) { @@ -212,6 +214,7 @@
> idpf_ptp_get_cross_time(struct idpf_adapter *adapter,
> return err;
> }
>
> +RTE_EXPORT_INTERNAL_SYMBOL(idpf_ptp_set_dev_clk_time)
> int
> idpf_ptp_set_dev_clk_time(struct idpf_adapter *adapter, uint64_t time) {
> @@ -256,6 +259,7 @@ idpf_ptp_adj_dev_clk_time(struct idpf_adapter
> *adapter, int64_t delta)
> return err;
> }
>
> +RTE_EXPORT_INTERNAL_SYMBOL(idpf_ptp_adj_dev_clk_fine)
> int
> idpf_ptp_adj_dev_clk_fine(struct idpf_adapter *adapter, uint64_t incval) {
> @@ -487,6 +491,7 @@ idpf_ptp_read_src_clk_reg_mailbox(struct
> idpf_adapter *adapter,
> *
> * Return: 0 on success, -errno otherwise.
> */
> +RTE_EXPORT_INTERNAL_SYMBOL(idpf_ptp_read_src_clk_reg)
> int
> idpf_ptp_read_src_clk_reg(struct idpf_adapter *adapter, uint64_t *src_clk) {
> diff --git a/drivers/net/intel/idpf/idpf_ptp.h
> b/drivers/net/intel/idpf/idpf_ptp.h
> index 0c901440fb..851cdad027 100644
> --- a/drivers/net/intel/idpf/idpf_ptp.h
> +++ b/drivers/net/intel/idpf/idpf_ptp.h
> @@ -88,13 +88,17 @@ struct idpf_ptp_dev_timers {
> uint64_t dev_clk_time_ns;
> };
>
> +__rte_internal
> int idpf_ptp_get_caps(struct idpf_adapter *adapter);
> +__rte_internal
> int idpf_ptp_read_src_clk_reg(struct idpf_adapter *adapter, uint64_t
> *src_clk); int idpf_ptp_get_dev_clk_time(struct idpf_adapter *adapter,
> struct idpf_ptp_dev_timers *dev_clk_time); int
> idpf_ptp_get_cross_time(struct idpf_adapter *adapter,
> struct idpf_ptp_dev_timers *cross_time);
> +__rte_internal
> int idpf_ptp_set_dev_clk_time(struct idpf_adapter *adapter, uint64_t time);
> +__rte_internal
> int idpf_ptp_adj_dev_clk_fine(struct idpf_adapter *adapter, uint64_t incval);
> int idpf_ptp_adj_dev_clk_time(struct idpf_adapter *adapter, int64_t delta);
> int idpf_ptp_get_vport_tstamps_caps(struct idpf_vport *vport);
> --
> 2.34.1
More information about the dev
mailing list