Re: [PATCH net-next 6/7] net: dsa: netc: add PTP two-step timestamping support

From: Vadim Fedorenko

Date: Wed Jul 29 2026 - 10:01:55 EST


On 28/07/2026 11:45, wei.fang@xxxxxxxxxxx wrote:
From: Wei Fang <wei.fang@xxxxxxx>

Add two-step TX timestamping and RX timestamping for the NETC switch.
One-step TX timestamping is not supported yet.

For RX, install ingress port filter table (IPFT) rules that redirect PTP
frames to the CPU port. Support L2, L4 over IPv4 and L4 over IPv6, for
both event and general messages, selected via the hwtstamp rx_filter.
The hardware prepends a To_Host subtype 1 tag carrying the 64-bit ingress
timestamp. The tagger extracts it into the skb control buffer, and
netc_port_rxtstamp() copies it into skb_hwtstamps().

For two-step TX, clone the skb and allocate a 4-bit timestamp request ID,
then queue the clone on a per-port list. netc_xmit() emits a To_Port
subtype 2 tag carrying that ID. The hardware echoes the ID back in a
generated To_Host subtype 2 response frame together with the 64-bit
transmit timestamp. The tagger dispatches the ID and timestamp to the
switch driver through the twostep_tstamp_handler callback registered in
netc_tagger_data, which matches the queued clone and completes it via
skb_complete_tx_timestamp(), then frees the response skb. Non-PTP frames
keep using the To_Port subtype 0 tag on the xmit fast path.

The two-step response frame carries no payload; its total length is only
26 bytes (12 bytes of DMAC and SMAC plus a 14-byte switch tag). By the
time netc_rcv() sees it, skb->data already points 2 bytes into the switch
tag, past the TPID shared with the Ethernet header, so skb->len is only
12. Since the tag pointer is at (skb->data - 2), the pskb_may_pull() check
must use NETC_TAG_MAX_LEN - 2 rather than NETC_TAG_MAX_LEN. Otherwise
pskb_may_pull() drops the response frame and breaks PTP synchronization.

Add the To_Port subtype 2 and To_Host subtype 1/2 tag structures, extend
netc_xmit() to select the tag based on ptp_flag in the skb control buffer,
and add netc_connect()/netc_disconnect() to manage the per-switch
netc_tagger_data allocation. Grab the PTP timer's pci_dev in netc_setup()
so get_ts_info() can report its PHC index, and release it in the teardown
and error paths.

Signed-off-by: Wei Fang <wei.fang@xxxxxxx>
---
drivers/net/dsa/netc/Kconfig | 1 +
drivers/net/dsa/netc/Makefile | 3 +-
drivers/net/dsa/netc/netc_main.c | 72 +++++
drivers/net/dsa/netc/netc_platform.c | 1 +
drivers/net/dsa/netc/netc_ptp.c | 411 +++++++++++++++++++++++++++
drivers/net/dsa/netc/netc_switch.h | 35 +++
include/linux/dsa/tag_netc.h | 23 ++
net/dsa/tag_netc.c | 120 +++++++-
8 files changed, 658 insertions(+), 8 deletions(-)
create mode 100644 drivers/net/dsa/netc/netc_ptp.c

[...]

+int netc_get_ts_info(struct dsa_switch *ds, int port,
+ struct kernel_ethtool_ts_info *info)
+{
+ struct netc_switch *priv = ds->priv;
+
+ info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_RX_SOFTWARE |
+ SOF_TIMESTAMPING_SOFTWARE;

SOF_TIMESTAMPING_RX_SOFTWARE and SOF_TIMESTAMPING_SOFTWARE are available by default, no need to add them.

the code doesn't have skb_tx_timestamp() calls, I wonder how is
SOF_TIMESTAMPING_TX_SOFTWARE implemented?

+
+ info->phc_index = netc_get_phc_index(priv);
+ if (info->phc_index < 0)
+ return 0;
+
+ info->so_timestamping |= SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+
+ info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);
+
+ info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
+ BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) |
+ BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
+ BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT);
+
+ return 0;
+}