From: James Hilliard <james.hilliard1@gmail.com>
To: "Russell King" <linux@armlinux.org.uk>,
"Andrew Lunn" <andrew@lunn.ch>,
"Heiner Kallweit" <hkallweit1@gmail.com>,
"David S. Miller" <davem@davemloft.net>,
"Jakub Kicinski" <kuba@kernel.org>,
"Paolo Abeni" <pabeni@redhat.com>,
"Joakim Zhang" <qiangqing.zhang@nxp.com>,
"Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>,
"Maxime Chevallier" <maxime.chevallier@bootlin.com>,
"Andrew Lunn" <andrew+netdev@lunn.ch>,
"Maxime Coquelin" <mcoquelin.stm32@gmail.com>,
"Alexandre Torgue" <alexandre.torgue@foss.st.com>,
"Christian Marangi" <ansuelsmth@gmail.com>,
"Tiezhu Yang" <yangtiezhu@loongson.cn>,
"Huacai Chen" <chenhuacai@kernel.org>,
"Alexei Starovoitov" <ast@kernel.org>,
"Daniel Borkmann" <daniel@iogearbox.net>,
"Jesper Dangaard Brouer" <hawk@kernel.org>,
"John Fastabend" <john.fastabend@gmail.com>,
"Stanislav Fomichev" <sdf@fomichev.me>,
"Serge Semin" <fancer.lancer@gmail.com>,
"Suraj Jaiswal" <quic_jsuraj@quicinc.com>,
"Richard Cochran" <richardcochran@gmail.com>,
"Joao Pinto" <Joao.Pinto@synopsys.com>,
"Vladimir Oltean" <vladimir.oltean@nxp.com>,
"Ong Boon Leong" <boon.leong.ong@intel.com>,
"Voon Weifeng" <weifeng.voon@intel.com>,
"Song, Yoong Siang" <yoong.siang.song@intel.com>,
"Linus Walleij" <linusw@kernel.org>,
"Martin Blumenstingl" <martin.blumenstingl@googlemail.com>,
"Magnus Karlsson" <magnus.karlsson@intel.com>,
"Maciej Fijalkowski" <maciej.fijalkowski@intel.com>,
"Simon Horman" <horms@kernel.org>,
"Björn Töpel" <bjorn@kernel.org>,
"Thierry Reding" <thierry.reding@kernel.org>,
"Jonathan Hunter" <jonathanh@nvidia.com>,
"Chen-Yu Tsai" <wens@kernel.org>,
"Jernej Skrabec" <jernej.skrabec@gmail.com>,
"Samuel Holland" <samuel@sholland.org>,
"Eric Dumazet" <edumazet@kernel.org>
Cc: Richard Genoud <richard.genoud@bootlin.com>,
Alastair D'Silva <alastair@d-silva.org>,
Maxime Ripard <mripard@kernel.org>,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-stm32@st-md-mailman.stormreply.com,
linux-arm-kernel@lists.infradead.org, bpf@vger.kernel.org,
ZhaoJinming <zhaojinming@uniontech.com>,
Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>,
Ding Hui <dinghui1111@163.com>,
James Hilliard <james.hilliard1@gmail.com>,
linux-tegra@vger.kernel.org, linux-sunxi@lists.linux.dev
Subject: [PATCH net v4 05/15] net: stmmac: serialize and retain PHC configuration across reset
Date: Sat, 26 Sep 2026 09:49:00 -0600 [thread overview]
Message-ID: <20260926-submit-stmmac-reset-fixes-v1-v4-5-ec1c0250b3c9@gmail.com> (raw)
In-Reply-To: <20260926-submit-stmmac-reset-fixes-v1-v4-0-ec1c0250b3c9@gmail.com>
Keep the frequency correction, PEROUT requests and EXTTS selection
independently of timestamp register contents. Cache PPS requests before
converting units so they can be replayed after reset.
Serialize timestamp writers and devlink timestamp-mode updates with a
mutex, and let atomic gettime callers observe a reset gate under
ptp_lock. Provide a common replay helper for later reset transactions,
without changing PHC registration lifetime.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 7 ++
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 19 +++-
drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c | 131 +++++++++++++++++++---
3 files changed, 141 insertions(+), 16 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index c7c876408d85..aa09b2defcd9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -337,6 +337,12 @@ struct stmmac_priv {
int use_riwt;
int irq_wake;
rwlock_t ptp_lock;
+ /* Serialize PHC changes with a hardware reset; gettime uses ptp_lock. */
+ struct mutex ptp_mutex;
+ bool ptp_blocked;
+ long ptp_scaled_ppm;
+ u32 ptp_perout;
+ u32 ptp_extts;
/* Protects auxiliary snapshot registers from concurrent access. */
struct mutex aux_ts_lock;
wait_queue_head_t tstamp_busy_wait;
@@ -404,6 +410,7 @@ void stmmac_set_ethtool_ops(struct net_device *netdev);
void stmmac_ptp_register(struct stmmac_priv *priv);
void stmmac_ptp_unregister(struct stmmac_priv *priv);
+int stmmac_ptp_restore(struct stmmac_priv *priv);
int stmmac_xdp_open(struct net_device *dev);
void stmmac_xdp_release(struct net_device *dev);
int stmmac_get_phy_intf_sel(phy_interface_t interface);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 4f3d452c3503..8b0bc7c46df9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -941,6 +941,11 @@ static void stmmac_setup_ptp(struct stmmac_priv *priv)
{
int ret;
+ priv->ptp_scaled_ppm = 0;
+ priv->ptp_perout = 0;
+ priv->ptp_extts = 0;
+ priv->ptp_blocked = false;
+
ret = clk_prepare_enable(priv->plat->clk_ptp_ref);
if (ret < 0)
netdev_warn(priv->dev,
@@ -6285,7 +6290,8 @@ static void stmmac_common_interrupt(struct stmmac_priv *priv)
for (queue = 0; queue < queues_count; queue++)
stmmac_host_mtl_irq_status(priv, priv->hw, queue);
- stmmac_timestamp_interrupt(priv, priv);
+ if (!READ_ONCE(priv->ptp_blocked))
+ stmmac_timestamp_interrupt(priv, priv);
}
}
@@ -7696,6 +7702,14 @@ static int stmmac_dl_ts_coarse_set(struct devlink *dl, u32 id,
{
struct stmmac_devlink_priv *dl_priv = devlink_priv(dl);
struct stmmac_priv *priv = dl_priv->stmmac_priv;
+ unsigned long flags;
+
+ mutex_lock(&priv->ptp_mutex);
+ if (priv->ptp_blocked) {
+ mutex_unlock(&priv->ptp_mutex);
+ return -EBUSY;
+ }
+ write_lock_irqsave(&priv->ptp_lock, flags);
priv->tsfupdt_coarse = ctx->val.vbool;
@@ -7708,6 +7722,8 @@ static int stmmac_dl_ts_coarse_set(struct devlink *dl, u32 id,
* reconfigure the systime, subsecond increment and addend.
*/
stmmac_update_subsecond_increment(priv);
+ write_unlock_irqrestore(&priv->ptp_lock, flags);
+ mutex_unlock(&priv->ptp_mutex);
return 0;
}
@@ -8048,6 +8064,7 @@ static int __stmmac_dvr_probe(struct device *device,
mutex_init(&priv->lock);
rwlock_init(&priv->ptp_lock);
+ mutex_init(&priv->ptp_mutex);
stmmac_fpe_init(priv);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
index 3bfcc9760dce..bc6fe0c87e01 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
@@ -12,6 +12,16 @@
#define PTP_SAFE_TIME_OFFSET_NS 500000
+static int stmmac_ptp_begin(struct stmmac_priv *priv)
+{
+ mutex_lock(&priv->ptp_mutex);
+ if (priv->ptp_blocked) {
+ mutex_unlock(&priv->ptp_mutex);
+ return -EBUSY;
+ }
+ return 0;
+}
+
/**
* stmmac_adjust_freq
*
@@ -28,14 +38,21 @@ static int stmmac_adjust_freq(struct ptp_clock_info *ptp, long scaled_ppm)
container_of(ptp, struct stmmac_priv, ptp_clock_ops);
unsigned long flags;
u32 addend;
+ int ret;
- addend = adjust_by_scaled_ppm(priv->default_addend, scaled_ppm);
+ ret = stmmac_ptp_begin(priv);
+ if (ret)
+ return ret;
write_lock_irqsave(&priv->ptp_lock, flags);
- stmmac_config_addend(priv, priv->ptpaddr, addend);
+ addend = adjust_by_scaled_ppm(priv->default_addend, scaled_ppm);
+ ret = stmmac_config_addend(priv, priv->ptpaddr, addend);
+ if (!ret)
+ priv->ptp_scaled_ppm = scaled_ppm;
write_unlock_irqrestore(&priv->ptp_lock, flags);
+ mutex_unlock(&priv->ptp_mutex);
- return 0;
+ return ret;
}
/**
@@ -57,6 +74,10 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta)
bool xmac, est_rst = false;
int ret;
+ ret = stmmac_ptp_begin(priv);
+ if (ret)
+ return ret;
+
xmac = dwmac_is_xmac(priv->plat->core_type);
if (delta < 0) {
@@ -110,6 +131,7 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta)
netdev_err(priv->dev, "failed to configure EST\n");
}
+ mutex_unlock(&priv->ptp_mutex);
return 0;
}
@@ -128,14 +150,18 @@ static int stmmac_get_time(struct ptp_clock_info *ptp, struct timespec64 *ts)
container_of(ptp, struct stmmac_priv, ptp_clock_ops);
unsigned long flags;
u64 ns = 0;
+ int ret = 0;
read_lock_irqsave(&priv->ptp_lock, flags);
- stmmac_get_systime(priv, priv->ptpaddr, &ns);
+ if (priv->ptp_blocked)
+ ret = -EBUSY;
+ else
+ stmmac_get_systime(priv, priv->ptpaddr, &ns);
read_unlock_irqrestore(&priv->ptp_lock, flags);
*ts = ns_to_timespec64(ns);
- return 0;
+ return ret;
}
/**
@@ -153,25 +179,34 @@ static int stmmac_set_time(struct ptp_clock_info *ptp,
struct stmmac_priv *priv =
container_of(ptp, struct stmmac_priv, ptp_clock_ops);
unsigned long flags;
+ int ret;
+
+ ret = stmmac_ptp_begin(priv);
+ if (ret)
+ return ret;
write_lock_irqsave(&priv->ptp_lock, flags);
- stmmac_init_systime(priv, priv->ptpaddr, ts->tv_sec, ts->tv_nsec);
+ ret = stmmac_init_systime(priv, priv->ptpaddr, ts->tv_sec, ts->tv_nsec);
write_unlock_irqrestore(&priv->ptp_lock, flags);
+ mutex_unlock(&priv->ptp_mutex);
- return 0;
+ return ret;
}
-static int stmmac_enable(struct ptp_clock_info *ptp,
- struct ptp_clock_request *rq, int on)
+static int __stmmac_enable(struct ptp_clock_info *ptp,
+ struct ptp_clock_request *rq, int on)
{
struct stmmac_priv *priv =
container_of(ptp, struct stmmac_priv, ptp_clock_ops);
void __iomem *ptpaddr = priv->ptpaddr;
- struct stmmac_pps_cfg *cfg;
+ struct stmmac_pps_cfg pps, saved, *cfg = &pps;
int ret = -EOPNOTSUPP;
unsigned long flags;
u32 acr_value;
+ if (priv->plat->core_type == DWMAC_CORE_GMAC)
+ return dwmac1000_ptp_enable(ptp, rq, on);
+
switch (rq->type) {
case PTP_CLK_REQ_PEROUT: {
struct timespec64 curr_time;
@@ -182,8 +217,6 @@ static int stmmac_enable(struct ptp_clock_info *ptp,
if (rq->perout.flags)
return -EOPNOTSUPP;
- cfg = &priv->pps[rq->perout.index];
-
cfg->start.tv_sec = rq->perout.start.sec;
cfg->start.tv_nsec = rq->perout.start.nsec;
@@ -213,6 +246,7 @@ static int stmmac_enable(struct ptp_clock_info *ptp,
cfg->period.tv_sec = rq->perout.period.sec;
cfg->period.tv_nsec = rq->perout.period.nsec;
+ saved = *cfg;
write_lock_irqsave(&priv->ptp_lock, flags);
ret = stmmac_flex_pps_config(priv, priv->ioaddr,
@@ -220,6 +254,9 @@ static int stmmac_enable(struct ptp_clock_info *ptp,
priv->sub_second_inc,
priv->systime_flags);
write_unlock_irqrestore(&priv->ptp_lock, flags);
+ /* Some cores convert cfg->start to binary rollover units. */
+ if (!ret)
+ priv->pps[rq->perout.index] = saved;
break;
}
case PTP_CLK_REQ_EXTTS: {
@@ -265,6 +302,64 @@ static int stmmac_enable(struct ptp_clock_info *ptp,
return ret;
}
+static int stmmac_enable(struct ptp_clock_info *ptp,
+ struct ptp_clock_request *rq, int on)
+{
+ struct stmmac_priv *priv =
+ container_of(ptp, struct stmmac_priv, ptp_clock_ops);
+ int ret;
+
+ ret = stmmac_ptp_begin(priv);
+ if (ret)
+ return ret;
+ ret = __stmmac_enable(ptp, rq, on);
+ if (!ret) {
+ if (rq->type == PTP_CLK_REQ_PEROUT) {
+ if (on)
+ priv->ptp_perout |= BIT(rq->perout.index);
+ else
+ priv->ptp_perout &= ~BIT(rq->perout.index);
+ } else if (rq->type == PTP_CLK_REQ_EXTTS) {
+ priv->ptp_extts = on ? BIT(rq->extts.index) : 0;
+ }
+ }
+ mutex_unlock(&priv->ptp_mutex);
+ return ret;
+}
+
+/* Called with ptp_mutex held and PHC access blocked across the MAC reset. */
+int stmmac_ptp_restore(struct stmmac_priv *priv)
+{
+ struct ptp_clock_request rq = { .type = PTP_CLK_REQ_EXTTS };
+ unsigned long flags;
+ u64 ns = 0, period;
+ u32 addend;
+ int i, ret;
+
+ write_lock_irqsave(&priv->ptp_lock, flags);
+ addend = adjust_by_scaled_ppm(priv->default_addend, priv->ptp_scaled_ppm);
+ ret = stmmac_config_addend(priv, priv->ptpaddr, addend);
+ for (i = 0; !ret && i < STMMAC_PPS_MAX; i++) {
+ struct stmmac_pps_cfg cfg = priv->pps[i];
+
+ if (!(priv->ptp_perout & BIT(i)))
+ continue;
+ stmmac_get_systime(priv, priv->ptpaddr, &ns);
+ period = timespec64_to_ns(&cfg.period);
+ /* Retain phase, but move an expired target into the future. */
+ cfg.start = stmmac_calc_tas_basetime(timespec64_to_ktime(cfg.start),
+ ns + PTP_SAFE_TIME_OFFSET_NS, period);
+ ret = stmmac_flex_pps_config(priv, priv->ioaddr, i, &cfg, true,
+ priv->sub_second_inc, priv->systime_flags);
+ }
+ write_unlock_irqrestore(&priv->ptp_lock, flags);
+ if (ret || !priv->ptp_extts)
+ return ret;
+
+ rq.extts.index = __ffs(priv->ptp_extts);
+ return __stmmac_enable(&priv->ptp_clock_ops, &rq, 1);
+}
+
/**
* stmmac_get_syncdevicetime
* @device: current device time
@@ -287,9 +382,15 @@ static int stmmac_getcrosststamp(struct ptp_clock_info *ptp,
{
struct stmmac_priv *priv =
container_of(ptp, struct stmmac_priv, ptp_clock_ops);
+ int ret;
- return get_device_system_crosststamp(stmmac_get_syncdevicetime,
- priv, NULL, xtstamp);
+ ret = stmmac_ptp_begin(priv);
+ if (ret)
+ return ret;
+ ret = get_device_system_crosststamp(stmmac_get_syncdevicetime,
+ priv, NULL, xtstamp);
+ mutex_unlock(&priv->ptp_mutex);
+ return ret;
}
/* structure describing a PTP hardware clock */
@@ -323,7 +424,7 @@ const struct ptp_clock_info dwmac1000_ptp_clock_ops = {
.adjtime = stmmac_adjust_time,
.gettime64 = stmmac_get_time,
.settime64 = stmmac_set_time,
- .enable = dwmac1000_ptp_enable,
+ .enable = stmmac_enable,
};
/**
--
2.53.0
next prev parent reply other threads:[~2026-09-26 15:49 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-26 15:48 [PATCH net v4 00/15] net: stmmac: preserve datapath state across MTU and resume failures James Hilliard
2026-09-26 15:48 ` [PATCH net v4 01/15] net: stmmac: unwind the WoL IRQ after a safety IRQ request failure James Hilliard
2026-09-26 15:48 ` [PATCH net v4 02/15] net: stmmac: reuse the MDIO reset GPIO on resume James Hilliard
2026-09-30 4:51 ` netdev-bot+sashiko
2026-09-26 15:48 ` [PATCH net v4 03/15] net: phylink: allow stopping a suspended instance James Hilliard
2026-09-30 4:51 ` netdev-bot+sashiko
2026-09-26 15:48 ` [PATCH net v4 04/15] xsk: freeze deferred pool teardown during system sleep James Hilliard
2026-09-30 4:51 ` netdev-bot+sashiko
2026-09-26 15:49 ` James Hilliard [this message]
2026-09-30 4:51 ` [PATCH net v4 05/15] net: stmmac: serialize and retain PHC configuration across reset netdev-bot+sashiko
2026-09-26 15:49 ` [PATCH net v4 06/15] net: stmmac: leave the datapath running for normal-size MTU changes James Hilliard
2026-09-26 15:49 ` [PATCH net v4 07/15] net: stmmac: unwind partially allocated DMA configurations James Hilliard
2026-09-30 4:51 ` netdev-bot+sashiko
2026-09-26 15:49 ` [PATCH net v4 08/15] net: stmmac: keep DMA configurations at stable addresses James Hilliard
2026-09-30 4:51 ` netdev-bot+sashiko
2026-09-26 15:49 ` [PATCH net v4 09/15] net: stmmac: track datapath and power ownership across failed reopening James Hilliard
2026-09-30 4:51 ` netdev-bot+sashiko
2026-09-26 15:49 ` [PATCH net v4 10/15] net: stmmac: use the tracked datapath restart for XSK pool changes James Hilliard
2026-09-30 4:51 ` netdev-bot+sashiko
2026-09-26 15:49 ` [PATCH net v4 11/15] net: stmmac: restore TC offloads before restarting DMA James Hilliard
2026-09-30 4:51 ` netdev-bot+sashiko
2026-09-26 15:49 ` [PATCH net v4 12/15] xsk: allow drivers to retain DMA mappings independently of pools James Hilliard
2026-09-26 15:49 ` [PATCH net v4 13/15] net: stmmac: retain DMA memory until hardware shutdown completes James Hilliard
2026-09-30 4:51 ` netdev-bot+sashiko
2026-09-26 15:49 ` [PATCH net v4 14/15] net: stmmac: prepare device-local DMA interrupt quiescence James Hilliard
2026-09-30 4:52 ` netdev-bot+sashiko
2026-09-26 15:49 ` [PATCH net v4 15/15] net: stmmac: retain DMA resources across MTU changes James Hilliard
2026-09-30 4:52 ` netdev-bot+sashiko
2026-09-26 16:00 ` [PATCH net v4 00/15] net: stmmac: preserve datapath state across MTU and resume failures Maxime Chevallier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260926-submit-stmmac-reset-fixes-v1-v4-5-ec1c0250b3c9@gmail.com \
--to=james.hilliard1@gmail.com \
--cc=Joao.Pinto@synopsys.com \
--cc=alastair@d-silva.org \
--cc=alexandre.torgue@foss.st.com \
--cc=andrew+netdev@lunn.ch \
--cc=andrew@lunn.ch \
--cc=ansuelsmth@gmail.com \
--cc=ast@kernel.org \
--cc=bjorn@kernel.org \
--cc=boon.leong.ong@intel.com \
--cc=bpf@vger.kernel.org \
--cc=chenhuacai@kernel.org \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=dinghui1111@163.com \
--cc=edumazet@kernel.org \
--cc=fancer.lancer@gmail.com \
--cc=hawk@kernel.org \
--cc=hkallweit1@gmail.com \
--cc=horms@kernel.org \
--cc=jernej.skrabec@gmail.com \
--cc=john.fastabend@gmail.com \
--cc=jonathanh@nvidia.com \
--cc=kuba@kernel.org \
--cc=linusw@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-stm32@st-md-mailman.stormreply.com \
--cc=linux-sunxi@lists.linux.dev \
--cc=linux-tegra@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=lorenzo.bianconi@oss.qualcomm.com \
--cc=maciej.fijalkowski@intel.com \
--cc=magnus.karlsson@intel.com \
--cc=martin.blumenstingl@googlemail.com \
--cc=maxime.chevallier@bootlin.com \
--cc=mcoquelin.stm32@gmail.com \
--cc=mripard@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=qiangqing.zhang@nxp.com \
--cc=quic_jsuraj@quicinc.com \
--cc=richard.genoud@bootlin.com \
--cc=richardcochran@gmail.com \
--cc=rmk+kernel@armlinux.org.uk \
--cc=samuel@sholland.org \
--cc=sdf@fomichev.me \
--cc=thierry.reding@kernel.org \
--cc=vladimir.oltean@nxp.com \
--cc=weifeng.voon@intel.com \
--cc=wens@kernel.org \
--cc=yangtiezhu@loongson.cn \
--cc=yoong.siang.song@intel.com \
--cc=zhaojinming@uniontech.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox