* [PATCH net-next v3 0/2] net: stmmac: dwxgmac2: timestamp interrupt + Agilex5 fix
@ 2026-08-18 13:27 Zxyan Zhu
2026-08-18 13:27 ` [PATCH net-next v3 1/2] net: stmmac: dwxgmac2: add XGMAC timestamp interrupt support Zxyan Zhu
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Zxyan Zhu @ 2026-08-18 13:27 UTC (permalink / raw)
To: maxime.chevallier, mcoquelin.stm32, alexandre.torgue,
andrew+netdev, richardcochran
Cc: davem, edumazet, kuba, pabeni, netdev, linux-stm32,
linux-arm-kernel, linux-kernel,
muhammad.nazim.amirul.nazle.asmade, Zxyan Zhu
This series adds auxiliary snapshot (EXTTS) interrupt support to
DWXGMAC2/DWXLGMAC2 and fixes a regression it would introduce on the
Agilex5 cross-timestamp path.
Patch 1 wires up a dedicated DWXGMAC2 timestamp interrupt handler.
Before this change the XGMAC hwif entries used the generic stmmac_ptp
ops, whose timestamp_interrupt callback read the dwmac4 offset
GMAC_TIMESTAMP_STATUS (0xb20) instead of the XGMAC register at 0xd20,
and XGMAC_TSIE was never enabled, so auxiliary snapshot events were
never reported on XGMAC platforms.
Patch 1 also unmasks XGMAC_TSIE in XGMAC_INT_DEFAULT_EN. That makes the
new handler run from hardirq on every XGMAC timestamp event, which races
with the Agilex5 smtg_crosststamp() poll loop: the handler clears TSIS
by reading XGMAC_TIMESTAMP_STATUS before the poll loop in process
context can observe it, so getcrosststamp() times out. Patch 2 fixes
this by masking XGMAC_TSIE for the duration of the cross-timestamp so
the handler cannot steal TSIS while smtg_crosststamp() owns the
snapshot FIFO.
Patch 2 has been verified on Agilex5 hardware: with both patches
applied, smtg_crosststamp() no times out (no "Wait for time sync
operation timeout" in dmesg) and the PTP clock registers and operates
normally.
v1: https://lore.kernel.org/netdev/20260806-dwxgmac2-timestamp-irq-v1-1-c051c79c9d90@gmail.com/
v2: https://lore.kernel.org/netdev/20260810100221.9166-1-zxyan0222@gmail.com/
v3:
- Add patch 2 to mask XGMAC_TSIE during the Agilex5 cross-timestamp, so
enabling XGMAC_TSIE in patch 1 does not break getcrosststamp() on
Agilex5 XGMAC (reported by the netdev sashiko review, fixed approach
discussed with Maxime).
- Patch 2 verified on Agilex5 by Nazim Amirul (Tested-by tag carried on
patch 2).
Zxyan Zhu (2):
net: stmmac: dwxgmac2: add XGMAC timestamp interrupt support
net: stmmac: dwmac-socfpga: mask XGMAC_TSIE during cross-timestamp
.../ethernet/stmicro/stmmac/dwmac-socfpga.c | 11 +++++
.../net/ethernet/stmicro/stmmac/dwxgmac2.h | 2 +-
.../ethernet/stmicro/stmmac/dwxgmac2_core.c | 43 +++++++++++++++++++
drivers/net/ethernet/stmicro/stmmac/hwif.c | 4 +-
drivers/net/ethernet/stmicro/stmmac/hwif.h | 1 +
.../ethernet/stmicro/stmmac/stmmac_hwtstamp.c | 12 ++++++
.../net/ethernet/stmicro/stmmac/stmmac_ptp.h | 1 +
7 files changed, 71 insertions(+), 3 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH net-next v3 1/2] net: stmmac: dwxgmac2: add XGMAC timestamp interrupt support
2026-08-18 13:27 [PATCH net-next v3 0/2] net: stmmac: dwxgmac2: timestamp interrupt + Agilex5 fix Zxyan Zhu
@ 2026-08-18 13:27 ` Zxyan Zhu
2026-08-18 13:27 ` [PATCH net-next v3 2/2] net: stmmac: dwmac-socfpga: mask XGMAC_TSIE during cross-timestamp Zxyan Zhu
2026-08-18 15:04 ` [PATCH net-next v3 0/2] net: stmmac: dwxgmac2: timestamp interrupt + Agilex5 fix Jakub Kicinski
2 siblings, 0 replies; 5+ messages in thread
From: Zxyan Zhu @ 2026-08-18 13:27 UTC (permalink / raw)
To: maxime.chevallier, mcoquelin.stm32, alexandre.torgue,
andrew+netdev, richardcochran
Cc: davem, edumazet, kuba, pabeni, netdev, linux-stm32,
linux-arm-kernel, linux-kernel,
muhammad.nazim.amirul.nazle.asmade, Zxyan Zhu
DWXGMAC2 uses XGMAC_TIMESTAMP_STATUS at offset 0xd20, while the
generic stmmac PTP handler reads the dwmac4 offset GMAC_TIMESTAMP_STATUS
(0xb20). Before this change, the DWXGMAC2 and DWXLGMAC2 hwif entries
used &stmmac_ptp, whose timestamp_interrupt callback read the wrong
register and whose config_hw_tstamping callback never enabled the
XGMAC timestamp interrupt (XGMAC_TSIE was not in XGMAC_INT_DEFAULT_EN).
As a result, auxiliary snapshot events were never reported on XGMAC
platforms.
Add a dedicated DWXGMAC2 timestamp interrupt handler that:
- reads XGMAC_TIMESTAMP_STATUS before checking
STMMAC_FLAG_EXT_SNAPSHOT_EN, so that the timestamp interrupt status is
cleared even when auxiliary snapshots are disabled
- derives the pending auxiliary snapshot count from the persistent
ATSNS field instead of the transient AUXTSTRIG status bit
- generates the corresponding PTP_CLOCK_EXTTS events
Also enable XGMAC_TSIE in XGMAC_INT_DEFAULT_EN and hook the new
handler into the DWXGMAC2 and DWXLGMAC2 hwif entries.
Signed-off-by: Zxyan Zhu <zxyan0222@gmail.com>
---
.../net/ethernet/stmicro/stmmac/dwxgmac2.h | 2 +-
.../ethernet/stmicro/stmmac/dwxgmac2_core.c | 43 +++++++++++++++++++
drivers/net/ethernet/stmicro/stmmac/hwif.c | 4 +-
drivers/net/ethernet/stmicro/stmmac/hwif.h | 1 +
.../ethernet/stmicro/stmmac/stmmac_hwtstamp.c | 12 ++++++
.../net/ethernet/stmicro/stmmac/stmmac_ptp.h | 1 +
6 files changed, 60 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
index 61b6d45a02f5..76e2860a9517 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
@@ -87,7 +87,7 @@
#define XGMAC_TSIE BIT(12)
#define XGMAC_LPIIE BIT(5)
#define XGMAC_PMTIE BIT(4)
-#define XGMAC_INT_DEFAULT_EN (XGMAC_LPIIE | XGMAC_PMTIE)
+#define XGMAC_INT_DEFAULT_EN (XGMAC_LPIIE | XGMAC_PMTIE | XGMAC_TSIE)
#define XGMAC_Qx_TX_FLOW_CTRL(x) (0x00000070 + (x) * 4)
#define XGMAC_PT GENMASK(31, 16)
#define XGMAC_TFE BIT(1)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
index f02b434bbd50..b849cebf9b29 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
@@ -1154,6 +1154,49 @@ static int dwxgmac2_get_mac_tx_timestamp(struct mac_device_info *hw, u64 *ts)
return 0;
}
+void dwxgmac2_timestamp_interrupt(struct stmmac_priv *priv)
+{
+ u32 ts_status, pending_snapshots, acr_value, channel;
+ struct ptp_clock_event event;
+ unsigned long flags;
+ u64 ptp_time;
+ int i;
+
+ /* Read XGMAC_TIMESTAMP_STATUS to get the AUX snapshot
+ * count. This read also clears the TSIS bit in
+ * XGMAC_INT_STATUS.
+ * TX timestamp polling may have already cleared TSIS
+ * and AUXTSTRIG, so rely on ATSNS instead.
+ * TXTSC is cleared by XGMAC_TXTIMESTAMP_SEC, not by
+ * this register, so there is no conflict.
+ */
+ ts_status = readl(priv->ioaddr + XGMAC_TIMESTAMP_STATUS);
+
+ if (!(priv->plat->flags & STMMAC_FLAG_EXT_SNAPSHOT_EN))
+ return;
+
+ pending_snapshots = FIELD_GET(XGMAC_TIMESTAMP_ATSNS_MASK, ts_status);
+ if (!pending_snapshots)
+ return;
+
+ acr_value = readl(priv->ptpaddr + PTP_ACR);
+ channel = FIELD_GET(PTP_ACR_MASK, acr_value);
+ if (!channel)
+ return;
+ channel = ilog2(channel);
+
+ for (i = 0; i < pending_snapshots; i++) {
+ read_lock_irqsave(&priv->ptp_lock, flags);
+ stmmac_get_ptptime(priv, priv->ptpaddr, &ptp_time);
+ read_unlock_irqrestore(&priv->ptp_lock, flags);
+
+ event.type = PTP_CLOCK_EXTTS;
+ event.index = channel;
+ event.timestamp = ptp_time;
+ ptp_clock_event(priv->ptp_clock, &event);
+ }
+}
+
static int dwxgmac2_flex_pps_config(void __iomem *ioaddr, int index,
struct stmmac_pps_cfg *cfg, bool enable,
u32 sub_second_inc, u32 systime_flags)
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
index 511b0fd5e834..9718582b8480 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
@@ -258,7 +258,7 @@ static const struct stmmac_hwif_entry {
.dma = &dwxgmac210_dma_ops,
.mac = &dwxgmac210_ops,
.vlan = &dwxgmac210_vlan_ops,
- .hwtimestamp = &stmmac_ptp,
+ .hwtimestamp = &dwxgmac2_ptp,
.ptp = &stmmac_ptp_clock_ops,
.mode = NULL,
.tc = &dwmac510_tc_ops,
@@ -280,7 +280,7 @@ static const struct stmmac_hwif_entry {
.dma = &dwxgmac210_dma_ops,
.mac = &dwxlgmac2_ops,
.vlan = &dwxlgmac2_vlan_ops,
- .hwtimestamp = &stmmac_ptp,
+ .hwtimestamp = &dwxgmac2_ptp,
.ptp = &stmmac_ptp_clock_ops,
.mode = NULL,
.tc = &dwmac510_tc_ops,
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index e6317b94fff7..818ab3daa91c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -671,6 +671,7 @@ extern const struct stmmac_desc_ops ndesc_ops;
extern const struct stmmac_hwtimestamp stmmac_ptp;
extern const struct stmmac_hwtimestamp dwmac1000_ptp;
+extern const struct stmmac_hwtimestamp dwxgmac2_ptp;
extern const struct stmmac_mode_ops ring_mode_ops;
extern const struct stmmac_mode_ops chain_mode_ops;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
index b9a985fa772c..9d7d24259abd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
@@ -277,3 +277,15 @@ const struct stmmac_hwtimestamp dwmac1000_ptp = {
.get_ptptime = dwmac1000_get_ptptime,
.timestamp_interrupt = dwmac1000_timestamp_interrupt,
};
+
+const struct stmmac_hwtimestamp dwxgmac2_ptp = {
+ .config_hw_tstamping = config_hw_tstamping,
+ .init_systime = init_systime,
+ .config_sub_second_increment = config_sub_second_increment,
+ .config_addend = config_addend,
+ .adjust_systime = adjust_systime,
+ .get_systime = get_systime,
+ .get_ptptime = get_ptptime,
+ .timestamp_interrupt = dwxgmac2_timestamp_interrupt,
+ .hwtstamp_correct_latency = hwtstamp_correct_latency,
+};
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
index 3fe0e3a80e80..dade09614163 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
@@ -103,6 +103,7 @@ int dwmac1000_ptp_enable(struct ptp_clock_info *ptp,
void dwmac1000_get_ptptime(void __iomem *ptpaddr, u64 *ptp_time);
void dwmac1000_timestamp_interrupt(struct stmmac_priv *priv);
+void dwxgmac2_timestamp_interrupt(struct stmmac_priv *priv);
extern const struct ptp_clock_info stmmac_ptp_clock_ops;
extern const struct ptp_clock_info dwmac1000_ptp_clock_ops;
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH net-next v3 2/2] net: stmmac: dwmac-socfpga: mask XGMAC_TSIE during cross-timestamp
2026-08-18 13:27 [PATCH net-next v3 0/2] net: stmmac: dwxgmac2: timestamp interrupt + Agilex5 fix Zxyan Zhu
2026-08-18 13:27 ` [PATCH net-next v3 1/2] net: stmmac: dwxgmac2: add XGMAC timestamp interrupt support Zxyan Zhu
@ 2026-08-18 13:27 ` Zxyan Zhu
2026-08-18 15:07 ` Andrew Lunn
2026-08-18 15:04 ` [PATCH net-next v3 0/2] net: stmmac: dwxgmac2: timestamp interrupt + Agilex5 fix Jakub Kicinski
2 siblings, 1 reply; 5+ messages in thread
From: Zxyan Zhu @ 2026-08-18 13:27 UTC (permalink / raw)
To: maxime.chevallier, mcoquelin.stm32, alexandre.torgue,
andrew+netdev, richardcochran
Cc: davem, edumazet, kuba, pabeni, netdev, linux-stm32,
linux-arm-kernel, linux-kernel,
muhammad.nazim.amirul.nazle.asmade, Zxyan Zhu
The Agilex5 smtg_crosststamp() handler arms an internal auxiliary
snapshot, toggles GPO0 and then polls XGMAC_INT_STATUS for TSIS in
process context to learn that the snapshot is ready.
Once XGMAC_TSIE is unmasked (done by a companion change that enables it
in XGMAC_INT_DEFAULT_EN), the DWXGMAC2 timestamp interrupt handler runs
from hardirq on every timestamp event and clears TSIS by reading
XGMAC_TIMESTAMP_STATUS. That read can win the race against the poll
loop, which then times out and makes PTP_SYS_OFFSET_PRECISE fail with
"Wait for time sync operation timeout".
Mask XGMAC_TSIE around the snapshot trigger and FIFO read so the hardirq
handler cannot clear TSIS while smtg_crosststamp() owns it, and restore
it on every return path.
Tested-by: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@altera.com>
Signed-off-by: Zxyan Zhu <zxyan0222@gmail.com>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
index 1d7f0a57d288..a4d00bf81423 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
@@ -310,6 +310,13 @@ static int smtg_crosststamp(ktime_t *device, struct system_counterval_t *system,
if (priv->plat->flags & STMMAC_FLAG_EXT_SNAPSHOT_EN)
return -EBUSY;
+ /* The XGMAC timestamp interrupt handler clears TSIS by reading
+ * XGMAC_TIMESTAMP_STATUS, which would race with the TSIS poll
+ * below. Mask XGMAC_TSIE for the duration of the cross-timestamp
+ * so the handler does not run while we own the snapshot FIFO.
+ */
+ stmmac_mac_irq_modify(priv, XGMAC_TSIE, 0);
+
mutex_lock(&priv->aux_ts_lock);
/* Enable Internal snapshot trigger */
acr_value = readl(ptpaddr + PTP_ACR);
@@ -329,6 +336,7 @@ static int smtg_crosststamp(ktime_t *device, struct system_counterval_t *system,
break;
default:
mutex_unlock(&priv->aux_ts_lock);
+ stmmac_mac_irq_modify(priv, 0, XGMAC_TSIE);
return -EINVAL;
}
writel(acr_value, ptpaddr + PTP_ACR);
@@ -353,6 +361,7 @@ static int smtg_crosststamp(ktime_t *device, struct system_counterval_t *system,
ret = readl_poll_timeout(priv->ioaddr + XGMAC_INT_STATUS, v,
(v & XGMAC_INT_TSIS), 100, 10000);
if (ret) {
+ stmmac_mac_irq_modify(priv, 0, XGMAC_TSIE);
netdev_err(priv->dev, "%s: Wait for time sync operation timeout\n",
__func__);
return ret;
@@ -375,6 +384,8 @@ static int smtg_crosststamp(ktime_t *device, struct system_counterval_t *system,
read_unlock_irqrestore(&priv->ptp_lock, flags);
}
+ stmmac_mac_irq_modify(priv, 0, XGMAC_TSIE);
+
get_smtgtime(priv->mii, SMTG_MDIO_ADDR, &smtg_time);
system->cycles = smtg_time;
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH net-next v3 0/2] net: stmmac: dwxgmac2: timestamp interrupt + Agilex5 fix
2026-08-18 13:27 [PATCH net-next v3 0/2] net: stmmac: dwxgmac2: timestamp interrupt + Agilex5 fix Zxyan Zhu
2026-08-18 13:27 ` [PATCH net-next v3 1/2] net: stmmac: dwxgmac2: add XGMAC timestamp interrupt support Zxyan Zhu
2026-08-18 13:27 ` [PATCH net-next v3 2/2] net: stmmac: dwmac-socfpga: mask XGMAC_TSIE during cross-timestamp Zxyan Zhu
@ 2026-08-18 15:04 ` Jakub Kicinski
2 siblings, 0 replies; 5+ messages in thread
From: Jakub Kicinski @ 2026-08-18 15:04 UTC (permalink / raw)
To: Zxyan Zhu
Cc: maxime.chevallier, mcoquelin.stm32, alexandre.torgue,
andrew+netdev, richardcochran, davem, edumazet, pabeni, netdev,
linux-stm32, linux-arm-kernel, linux-kernel,
muhammad.nazim.amirul.nazle.asmade
On Tue, 18 Aug 2026 21:27:20 +0800 Zxyan Zhu wrote:
> This series adds auxiliary snapshot (EXTTS) interrupt support to
> DWXGMAC2/DWXLGMAC2 and fixes a regression it would introduce on the
> Agilex5 cross-timestamp path.
## Form letter - net-next-closed
The merge window for v7.3 has started, and therefore net-next is closed
for new drivers, features, code refactoring and optimizations.
We will only consider applying net-next patches which were posted
before the announcement:
https://lore.kernel.org/20260816155953.072d73da@kernel.org
Fixes are obviously welcome at any time. net-next patches may be sent
for review and discussion only with an RFC tag.
Please repost when net-next reopens.
See: https://www.kernel.org/doc/html/next/process/maintainer-netdev.html#development-cycle
--
pw-bot: defer
pv-bot: closed
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net-next v3 2/2] net: stmmac: dwmac-socfpga: mask XGMAC_TSIE during cross-timestamp
2026-08-18 13:27 ` [PATCH net-next v3 2/2] net: stmmac: dwmac-socfpga: mask XGMAC_TSIE during cross-timestamp Zxyan Zhu
@ 2026-08-18 15:07 ` Andrew Lunn
0 siblings, 0 replies; 5+ messages in thread
From: Andrew Lunn @ 2026-08-18 15:07 UTC (permalink / raw)
To: Zxyan Zhu
Cc: maxime.chevallier, mcoquelin.stm32, alexandre.torgue,
andrew+netdev, richardcochran, davem, edumazet, kuba, pabeni,
netdev, linux-stm32, linux-arm-kernel, linux-kernel,
muhammad.nazim.amirul.nazle.asmade
On Tue, Aug 18, 2026 at 09:27:22PM +0800, Zxyan Zhu wrote:
> The Agilex5 smtg_crosststamp() handler arms an internal auxiliary
> snapshot, toggles GPO0 and then polls XGMAC_INT_STATUS for TSIS in
> process context to learn that the snapshot is ready.
>
> Once XGMAC_TSIE is unmasked (done by a companion change that enables it
> in XGMAC_INT_DEFAULT_EN), the DWXGMAC2 timestamp interrupt handler runs
> from hardirq on every timestamp event and clears TSIS by reading
> XGMAC_TIMESTAMP_STATUS. That read can win the race against the poll
> loop, which then times out and makes PTP_SYS_OFFSET_PRECISE fail with
> "Wait for time sync operation timeout".
>
> Mask XGMAC_TSIE around the snapshot trigger and FIFO read so the hardirq
> handler cannot clear TSIS while smtg_crosststamp() owns it, and restore
> it on every return path.
Did you look at the other system which implement crosststamp?
dwmac-intel.c? Does it need similar changes?
Andrew
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-08-18 15:07 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-18 13:27 [PATCH net-next v3 0/2] net: stmmac: dwxgmac2: timestamp interrupt + Agilex5 fix Zxyan Zhu
2026-08-18 13:27 ` [PATCH net-next v3 1/2] net: stmmac: dwxgmac2: add XGMAC timestamp interrupt support Zxyan Zhu
2026-08-18 13:27 ` [PATCH net-next v3 2/2] net: stmmac: dwmac-socfpga: mask XGMAC_TSIE during cross-timestamp Zxyan Zhu
2026-08-18 15:07 ` Andrew Lunn
2026-08-18 15:04 ` [PATCH net-next v3 0/2] net: stmmac: dwxgmac2: timestamp interrupt + Agilex5 fix Jakub Kicinski
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.