[PATCH net v2] net: stmmac: re-apply taprio offload in __stmmac_open()
Lorenzo Bianconi
lorenzo.bianconi at oss.qualcomm.com
Sat Aug 29 02:56:33 PDT 2026
The core soft reset issued in stmmac_init_dma_engine() clears the
MTL_EST registers, but nothing re-applies the taprio offload after it:
priv->est->enable stays true while the hardware EST block is left
disabled. The TX/XDP paths then keep dropping frames larger than
priv->est->max_sdu[] and taprio is reported as offloaded, although the
EST block is not programmed.
Re-apply the taprio offload in __stmmac_open() after PTP is up. The
base time is recomputed from the reserved base time and the current PTP
time, since the timestamp counter has been re-initialized and the
previously programmed base time is stale.
Introduce the stmmac_setup_est utility routine.
Fixes: b60189e0392f ("net: stmmac: Integrate EST with TAPRIO scheduler API")
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi at oss.qualcomm.com>
---
Changes in v2:
- Rename stmmac_est_reconfigure() in stmmac_setup_est().
- Rely on stmmac_setup_est() in tc_taprio_configure().
- Link to v1: https://lore.kernel.org/r/20260825-stmmac-est-reapply-after-open-v1-1-dfa80735e0a1@oss.qualcomm.com
---
drivers/net/ethernet/stmicro/stmmac/stmmac_est.c | 33 +++++++++++++++++++++++
drivers/net/ethernet/stmicro/stmmac/stmmac_est.h | 2 ++
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 16 +++++++++--
drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c | 26 ++----------------
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 27 ++++++-------------
5 files changed, 59 insertions(+), 45 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_est.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_est.c
index afc516059b89..bbebd33c8a88 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_est.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_est.c
@@ -80,6 +80,39 @@ static int est_configure(struct stmmac_priv *priv, struct stmmac_est *cfg,
return 0;
}
+int stmmac_setup_est(struct stmmac_priv *priv)
+{
+ struct timespec64 current_time, time;
+ ktime_t current_time_ns, basetime;
+ u64 cycle_time;
+ int err;
+
+ mutex_lock(&priv->est_lock);
+
+ priv->ptp_clock_ops.gettime64(&priv->ptp_clock_ops, ¤t_time);
+ current_time_ns = timespec64_to_ktime(current_time);
+
+ time.tv_nsec = priv->est->btr_reserve[0];
+ time.tv_sec = priv->est->btr_reserve[1];
+ basetime = timespec64_to_ktime(time);
+
+ cycle_time = (u64)priv->est->ctr[1] * NSEC_PER_SEC + priv->est->ctr[0];
+
+ time = stmmac_calc_tas_basetime(basetime, current_time_ns, cycle_time);
+ priv->est->btr[0] = (u32)time.tv_nsec;
+ priv->est->btr[1] = (u32)time.tv_sec;
+
+ err = stmmac_est_configure(priv, priv, priv->est,
+ priv->plat->clk_ptp_rate);
+
+ mutex_unlock(&priv->est_lock);
+
+ if (err)
+ netdev_err(priv->dev, "failed to re-configure EST\n");
+
+ return err;
+}
+
static void est_irq_status(struct stmmac_priv *priv, struct net_device *dev,
struct stmmac_extra_stats *x, u32 txqcnt)
{
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_est.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_est.h
index f70221c9c84a..f620d3331c2c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_est.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_est.h
@@ -65,3 +65,5 @@
#define EST_GCL_DATA 0x00000034
extern const struct stmmac_est_ops dwmac510_est_ops;
+
+int stmmac_setup_est(struct stmmac_priv *priv);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index d576059c04df..b30036428188 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -48,6 +48,7 @@
#include "stmmac_ptp.h"
#include "stmmac_fpe.h"
#include "stmmac.h"
+#include "stmmac_est.h"
#include "stmmac_pcs.h"
#include "stmmac_xdp.h"
#include <linux/reset.h>
@@ -4153,11 +4154,22 @@ static int __stmmac_open(struct net_device *dev,
ret = stmmac_hw_setup(dev);
if (ret < 0) {
netdev_err(priv->dev, "%s: Hw setup failed\n", __func__);
- goto init_error;
+ return ret;
}
stmmac_setup_ptp(priv);
+ /* The core soft reset in stmmac_hw_setup() clears the MTL_EST
+ * registers, so re-apply the taprio offload after PTP is up.
+ */
+ if (priv->est && priv->est->enable) {
+ ret = stmmac_setup_est(priv);
+ if (ret < 0) {
+ priv->est->enable = false;
+ return ret;
+ }
+ }
+
stmmac_init_coalesce(priv);
phylink_start(priv->phylink);
@@ -4181,7 +4193,7 @@ static int __stmmac_open(struct net_device *dev,
hrtimer_cancel(&priv->dma_conf.tx_queue[chan].txtimer);
stmmac_release_ptp(priv);
-init_error:
+
return ret;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
index 960249960004..917ef7ddcae6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
@@ -8,6 +8,7 @@
Author: Rayagond Kokatanur <rayagond at vayavyalabs.com>
*******************************************************************************/
#include "stmmac.h"
+#include "stmmac_est.h"
#include "stmmac_ptp.h"
#define PTP_SAFE_TIME_OFFSET_NS 500000
@@ -55,7 +56,6 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta)
u32 quotient, reminder;
int neg_adj = 0;
bool xmac, est_rst = false;
- int ret;
xmac = dwmac_is_xmac(priv->plat->core_type);
@@ -84,30 +84,8 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta)
/* Calculate new basetime and re-configured EST after PTP time adjust. */
if (est_rst) {
- struct timespec64 current_time, time;
- ktime_t current_time_ns, basetime;
- u64 cycle_time;
-
- mutex_lock(&priv->est_lock);
- priv->ptp_clock_ops.gettime64(&priv->ptp_clock_ops, ¤t_time);
- current_time_ns = timespec64_to_ktime(current_time);
- time.tv_nsec = priv->est->btr_reserve[0];
- time.tv_sec = priv->est->btr_reserve[1];
- basetime = timespec64_to_ktime(time);
- cycle_time = (u64)priv->est->ctr[1] * NSEC_PER_SEC +
- priv->est->ctr[0];
- time = stmmac_calc_tas_basetime(basetime,
- current_time_ns,
- cycle_time);
-
- priv->est->btr[0] = (u32)time.tv_nsec;
- priv->est->btr[1] = (u32)time.tv_sec;
priv->est->enable = true;
- ret = stmmac_est_configure(priv, priv, priv->est,
- priv->plat->clk_ptp_rate);
- mutex_unlock(&priv->est_lock);
- if (ret)
- netdev_err(priv->dev, "failed to configure EST\n");
+ stmmac_setup_est(priv);
}
return 0;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index 14cabe76e53e..b41df317d73c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -10,6 +10,7 @@
#include "dwmac4.h"
#include "dwmac5.h"
#include "stmmac.h"
+#include "stmmac_est.h"
static void tc_fill_all_pass_entry(struct stmmac_tc_entry *entry)
{
@@ -968,8 +969,7 @@ static int tc_taprio_configure(struct stmmac_priv *priv,
{
u32 size, wid = priv->dma_cap.estwid, dep = priv->dma_cap.estdep;
struct netlink_ext_ack *extack = qopt->mqprio.extack;
- struct timespec64 time, current_time, qopt_time;
- ktime_t current_time_ns;
+ struct timespec64 time;
int i, ret = 0;
u64 ctr;
@@ -1069,34 +1069,23 @@ static int tc_taprio_configure(struct stmmac_priv *priv,
}
mutex_lock(&priv->est_lock);
- /* Adjust for real system time */
- priv->ptp_clock_ops.gettime64(&priv->ptp_clock_ops, ¤t_time);
- current_time_ns = timespec64_to_ktime(current_time);
- time = stmmac_calc_tas_basetime(qopt->base_time, current_time_ns,
- qopt->cycle_time);
-
- priv->est->btr[0] = (u32)time.tv_nsec;
- priv->est->btr[1] = (u32)time.tv_sec;
- qopt_time = ktime_to_timespec64(qopt->base_time);
- priv->est->btr_reserve[0] = (u32)qopt_time.tv_nsec;
- priv->est->btr_reserve[1] = (u32)qopt_time.tv_sec;
+ time = ktime_to_timespec64(qopt->base_time);
+ priv->est->btr_reserve[0] = (u32)time.tv_nsec;
+ priv->est->btr_reserve[1] = (u32)time.tv_sec;
ctr = qopt->cycle_time;
priv->est->ctr[0] = do_div(ctr, NSEC_PER_SEC);
priv->est->ctr[1] = (u32)ctr;
priv->est->ter = qopt->cycle_time_extension;
-
tc_taprio_map_maxsdu_txq(priv, qopt);
- ret = stmmac_est_configure(priv, priv, priv->est,
- priv->plat->clk_ptp_rate);
mutex_unlock(&priv->est_lock);
- if (ret) {
- netdev_err(priv->dev, "failed to configure EST\n");
+
+ ret = stmmac_setup_est(priv);
+ if (ret)
goto disable;
- }
ret = stmmac_fpe_map_preemption_class(priv, priv->dev, extack,
qopt->mqprio.preemptible_tcs);
---
base-commit: 2188569e7e1b0bc3f3b557dc97ab7a02befc11c8
change-id: 20260824-stmmac-est-reapply-after-open-181d70a15eb6
Best regards,
--
Lorenzo Bianconi <lorenzo.bianconi at oss.qualcomm.com>
More information about the linux-arm-kernel
mailing list