* [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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).