[PATCH net 2/2] net: stmmac: preserve FPE preemption class across qdisc replacement
Lorenzo Bianconi
lorenzo.bianconi at oss.qualcomm.com
Sat Aug 29 01:28:50 PDT 2026
The kernel replaces a root qdisc by creating the new qdisc first and
destroying the old one only afterwards (qdisc_create() then
qdisc_graft() -> notify_and_destroy()). For a cross-kind replace this
means the teardown of the old qdisc runs after the offload of the new
one.
This breaks the FPE preemption-class mapping when replacing between
qdiscs that both program it. For example replacing taprio with mqprio:
1. the mqprio offload (REPLACE) programs FPE_MTL_PREEMPTION_CLASS
with mqprio->preemptible_tcs
2. the old taprio is then torn down; tc_taprio_configure() runs the
TAPRIO_CMD_DESTROY path and resets the preemption class to 0
Track which root qdisc policy is currently offloaded in a new
priv->qdisc_type field and only clear the FPE preemption class during
teardown if the qdisc being destroyed actually owns it.
Fixes: 15d8a407a547 ("net: stmmac: support fp parameter of tc-taprio")
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi at oss.qualcomm.com>
---
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 7 +++++++
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 22 ++++++++++++++++++----
2 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 7582fca63741..957317ec1461 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -258,6 +258,12 @@ struct stmmac_msi {
char int_name_tx_irq[MTL_MAX_TX_QUEUES][IFNAMSIZ + 18];
};
+enum stmmac_qdisc_type {
+ STMMAC_QDISC_NONE = 0,
+ STMMAC_QDISC_MQPRIO,
+ STMMAC_QDISC_TAPRIO,
+};
+
struct stmmac_priv {
/* Frequently used values are kept adjacent for cache effect */
u32 tx_coal_frames[MTL_MAX_TX_QUEUES];
@@ -299,6 +305,7 @@ struct stmmac_priv {
/* Protect est parameters */
struct mutex est_lock;
struct stmmac_est *est;
+ enum stmmac_qdisc_type qdisc_type;
struct dma_features dma_cap;
struct stmmac_counters mmc;
int hw_cap_support;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index be8ddda2aa76..7fe587b47d52 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -1103,6 +1103,8 @@ static int tc_taprio_configure(struct stmmac_priv *priv,
if (ret)
goto disable;
+ priv->qdisc_type = STMMAC_QDISC_TAPRIO;
+
return 0;
disable:
@@ -1120,7 +1122,11 @@ static int tc_taprio_configure(struct stmmac_priv *priv,
mutex_unlock(&priv->est_lock);
}
- stmmac_fpe_map_preemption_class(priv, priv->dev, extack, 0);
+ if (priv->qdisc_type == STMMAC_QDISC_TAPRIO &&
+ qopt->cmd == TAPRIO_CMD_DESTROY) {
+ stmmac_fpe_map_preemption_class(priv, priv->dev, extack, 0);
+ priv->qdisc_type = STMMAC_QDISC_NONE;
+ }
return ret;
}
@@ -1266,9 +1272,15 @@ static void stmmac_reset_tc_mqprio(struct net_device *ndev,
{
struct stmmac_priv *priv = netdev_priv(ndev);
- netdev_reset_tc(ndev);
- netif_set_real_num_tx_queues(ndev, priv->plat->tx_queues_to_use);
- stmmac_fpe_map_preemption_class(priv, ndev, extack, 0);
+ if (priv->qdisc_type != STMMAC_QDISC_TAPRIO)
+ stmmac_fpe_map_preemption_class(priv, ndev, extack, 0);
+
+ if (priv->qdisc_type == STMMAC_QDISC_MQPRIO) {
+ netdev_reset_tc(ndev);
+ netif_set_real_num_tx_queues(ndev,
+ priv->plat->tx_queues_to_use);
+ priv->qdisc_type = STMMAC_QDISC_NONE;
+ }
}
static int tc_setup_dwmac510_mqprio(struct stmmac_priv *priv,
@@ -1318,6 +1330,8 @@ static int tc_setup_dwmac510_mqprio(struct stmmac_priv *priv,
if (err)
goto error_reset_num_tx_queues;
+ priv->qdisc_type = STMMAC_QDISC_MQPRIO;
+
return 0;
error_reset_num_tx_queues:
--
2.55.0
More information about the linux-arm-kernel
mailing list