[PATCH net-next v2] net: stmmac: fix mqprio and cbs combination

Lorenzo Bianconi lorenzo.bianconi at oss.qualcomm.com
Wed Oct 14 02:05:25 PDT 2026


The channel-mode mqprio offload and the CBS offload can currently not be
enabled at the same time. tc_mqprio_validate_chan_mode() refuses the
mqprio offload as soon as any TX queue is configured in AVB mode, and
tc_setup_cbs() refuses to enable CBS while the strict-priority scheduler
is active. As a result the combination is rejected whichever order the
two are configured in.

The strict-priority scheduler selected by the channel-mode mqprio offload
and the per-queue CBS shaper are stored in independent MTL fields on
dwmac4/EQoS cores (MTL_OPERATION_MODE.SCHALG vs MTL_ETS_CTRL.AVALG), so
the two checks are over-restrictive there. On XGMAC/XLGMAC they are not
independent: the TX scheduling algorithm and the CBS shaper share the
per-TC MTL_TCx_ETS_CONTROL.TSA field, so programming the scheduler
rewrites TSA on every queue and would disable CBS on any queue configured
in AVB mode.

Drop the checks and re-apply the AVB/CBS configuration with
stmmac_configure_cbs() after the TX algorithm is reprogrammed in
tc_mqprio_config_queue_prio() and stmmac_reset_tc_mqprio(), so the
combination is offloaded correctly on all cores. The stmmac_reinit_queues()
check is dropped as well, since a subsequent ndo_open restores the AVB
queues.

The following configuration, which was previously refused, now works:

  $ tc qdisc replace dev eth0 handle 100 parent root mqprio \
        num_tc 4 \
        map  0  0  0  0  0  1  2  3  0  0  0  0  0  0  0  0 \
        queues 1 at 0 1 at 1 1 at 2 1 at 3 mode channel hw 1
  $ tc qdisc replace dev eth0 parent 100:2 handle 102: cbs  \
        idleslope 800000 sendslope -1700000 hicredit 494    \
        locredit -1049 offload 0
  $ tc qdisc replace dev eth0 parent 100:3 handle 103: cbs  \
        idleslope 400000 sendslope -2100000 hicredit 247    \
        locredit -1296 offload 1
  $ tc qdisc replace dev eth0 parent 100:4 handle 104: cbs  \
        idleslope 200000 sendslope -2300000 hicredit 124    \
        locredit -1419 offload 1

Fixes: 47891d501e34 ("net: stmmac: add tc mqprio hw queue priority offload")
Tested-by: Daniel Thompson <daniel at riscstar.com>
Reviewed-by: Maxime Chevallier <maxime.chevallier at bootlin.com>
Reviewed-by: Daniel Thompson <daniel at riscstar.com>
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi at oss.qualcomm.com>
---
Changes in v2:
- Reconfigure AVB queues if necessary.
- Link to v1: https://lore.kernel.org/r/20261012-stmmac-mqprio-cbs-combo-v1-1-831e323eb4ef@oss.qualcomm.com
---
 drivers/net/ethernet/stmicro/stmmac/stmmac.h      |  1 +
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 10 +---------
 drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c   | 20 ++++----------------
 3 files changed, 6 insertions(+), 25 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 08b68441f9c8..120d01c04d61 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -440,6 +440,7 @@ static inline bool stmmac_xdp_is_enabled(struct stmmac_priv *priv)
 	return !!priv->xdp_prog;
 }
 
+void stmmac_configure_cbs(struct stmmac_priv *priv);
 void stmmac_disable_rx_queue(struct stmmac_priv *priv, u32 queue);
 void stmmac_enable_rx_queue(struct stmmac_priv *priv, u32 queue);
 void stmmac_disable_tx_queue(struct stmmac_priv *priv, u32 queue);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 56d89a696272..1fdb4ca56591 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3467,7 +3467,7 @@ static void stmmac_set_tx_queue_weight(struct stmmac_priv *priv)
  *  @priv: driver private structure
  *  Description: It is used for configuring CBS in AVB TX queues
  */
-static void stmmac_configure_cbs(struct stmmac_priv *priv)
+void stmmac_configure_cbs(struct stmmac_priv *priv)
 {
 	u8 tx_queues_count = priv->plat->tx_queues_to_use;
 	u32 mode_to_use;
@@ -7740,14 +7740,6 @@ int stmmac_reinit_queues(struct net_device *dev, u8 rx_cnt, u8 tx_cnt)
 	    tx_cnt < priv->xmit_qdisc.num_tx_queues)
 		return -EINVAL;
 
-	if (priv->xmit_qdisc.prio_offload) {
-		for (i = priv->plat->tx_queues_to_use; i < tx_cnt; i++) {
-			if (priv->plat->tx_queues_cfg[i].mode_to_use ==
-			    MTL_QUEUE_AVB)
-				return -EINVAL;
-		}
-	}
-
 	if (netif_running(dev))
 		stmmac_release(dev);
 
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index b09e9a89cee8..e137fb9012d4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -346,9 +346,6 @@ static int tc_setup_cbs(struct stmmac_priv *priv,
 	if (!priv->dma_cap.av)
 		return -EOPNOTSUPP;
 
-	if (qopt->enable && priv->xmit_qdisc.prio_offload)
-		return -EOPNOTSUPP;
-
 	port_transmit_rate_kbps = qopt->idleslope - qopt->sendslope;
 
 	if (qopt->enable) {
@@ -1288,6 +1285,8 @@ static int stmmac_reset_tc_mqprio(struct net_device *ndev,
 
 		stmmac_prog_mtl_tx_algorithms(priv, priv->hw,
 					      priv->plat->tx_sched_algorithm);
+		/* Re-configure AVB queues if necessary */
+		stmmac_configure_cbs(priv);
 		priv->xmit_qdisc.algo = priv->plat->tx_sched_algorithm;
 		priv->xmit_qdisc.prio_offload = false;
 	}
@@ -1334,6 +1333,8 @@ static void tc_mqprio_config_queue_prio(struct stmmac_priv *priv,
 	}
 
 	stmmac_prog_mtl_tx_algorithms(priv, priv->hw, MTL_TX_ALGORITHM_SP);
+	/* Re-configure AVB queues if necessary */
+	stmmac_configure_cbs(priv);
 	priv->xmit_qdisc.algo = MTL_TX_ALGORITHM_SP;
 	priv->xmit_qdisc.prio_offload = true;
 }
@@ -1341,7 +1342,6 @@ static void tc_mqprio_config_queue_prio(struct stmmac_priv *priv,
 static int tc_mqprio_validate_chan_mode(struct stmmac_priv *priv,
 					struct tc_mqprio_qopt_offload *mqprio)
 {
-	struct plat_stmmacenet_data *pdata = priv->plat;
 	struct tc_mqprio_qopt *qopt = &mqprio->qopt;
 	int i;
 
@@ -1351,18 +1351,6 @@ static int tc_mqprio_validate_chan_mode(struct stmmac_priv *priv,
 		return -EOPNOTSUPP;
 	}
 
-	/* Forcing strict priority conflicts with the CBS algorithm
-	 * of AVB queues, so reject the offload when any queue is
-	 * configured as AVB.
-	 */
-	for (i = 0; i < pdata->tx_queues_to_use; i++) {
-		if (pdata->tx_queues_cfg[i].mode_to_use == MTL_QUEUE_AVB) {
-			NL_SET_ERR_MSG_MOD(mqprio->extack,
-					   "SP conflicts with AVB queues");
-			return -EOPNOTSUPP;
-		}
-	}
-
 	for (i = 0; i < qopt->num_tc; i++) {
 		/* The offload switches the MTL scheduler to strict
 		 * priority, which only supports a 1:1 TC to TX queue

---
base-commit: 05b5019b01fb9443b09ae4ed34af1135a80a84c8
change-id: 20261012-stmmac-mqprio-cbs-combo-341f12749ce2

Best regards,
-- 
Lorenzo Bianconi <lorenzo.bianconi at oss.qualcomm.com>




More information about the linux-arm-kernel mailing list