[PATCH net-next v5 2/3] net: stmmac: align real_num_tx_queues to mqprio configuration
flat view
WARM2d
REVIEWED: 5 (5M)
From: Lorenzo Bianconi <hidden>
Date: 2026-10-06 10:46:53
Also in:
netdev
Subsystem:
networking drivers, stmmac ethernet driver, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Chevallier, Linus Torvalds
1 review trailer (1 from subsystem maintainers).
stmmac_hw_setup() unconditionally sets the number of real TX queues to
plat->tx_queues_to_use on every device open. When a tc-mqprio qdisc is
offloaded the driver reduces netif_set_real_num_tx_queues() to the number
of queues enabled by the offload, but the next device open reverts it to
plat->tx_queues_to_use while the netdev TC map is still the one programmed
by the qdisc, leaving the two inconsistent.
Track the number of TX queues enabled by the current qdisc configuration
in the per-qdisc state (priv->xmit_qdisc.num_tx_queues) and use it in
stmmac_hw_setup(). The field defaults to plat->tx_queues_to_use at probe
time and when the mqprio qdisc is destroyed, meaning no offload is active
and the number of real TX queues must match the number of queues the
driver allocated, and it is updated to the offloaded queue count on a
successful mqprio setup.
mqprio only validates the requested queue ranges against
dev->real_num_tx_queues, which can be larger than plat->tx_queues_to_use
while the interface has not been opened yet. Reject a qopt whose highest
referenced queue (offset + count) exceeds plat->tx_queues_to_use, so
xmit_qdisc.num_tx_queues can never be larger than the number of TX queues
the driver provisions. Otherwise stmmac_hw_setup() would expose TX queues
without an allocated DMA ring.
Refuse to lower the number of TX queues below the count required by the
active mqprio offload in stmmac_reinit_queues(), otherwise
netif_set_real_num_tx_queues() would leave real_num_tx_queues
inconsistent with the netdev TC map.
The issue has been reported by sashiko and the patch has been tested on
a Qualcomm RB3-Gen2 board.
Fixes: 195e4f409a40 ("net: stmmac: support fp parameter of tc-mqprio")
Tested-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Signed-off-by: Lorenzo Bianconi <redacted>
---
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 6 ++++++
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 12 +++++++++++-
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 13 +++++++++++++
3 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 4fc96b317d79..0052f2129297 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h@@ -299,6 +299,12 @@ struct stmmac_priv { /* Protect est parameters */ struct mutex est_lock; struct stmmac_est *est; + + struct { + bool enabled; + u32 num_tx_queues; + } xmit_qdisc; + struct dma_features dma_cap; struct stmmac_counters mmc; int hw_cap_support;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 0c381ae0d0ff..9c03d21ebfcc 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c@@ -3780,7 +3780,7 @@ static int stmmac_hw_setup(struct net_device *dev) /* Configure real RX and TX queues */ netif_set_real_num_rx_queues(dev, priv->plat->rx_queues_to_use); - netif_set_real_num_tx_queues(dev, priv->plat->tx_queues_to_use); + netif_set_real_num_tx_queues(dev, priv->xmit_qdisc.num_tx_queues); /* Start the ball rolling... */ stmmac_start_all_dma(priv);
@@ -7707,6 +7707,10 @@ int stmmac_reinit_queues(struct net_device *dev, u8 rx_cnt, u8 tx_cnt) struct stmmac_priv *priv = netdev_priv(dev); int ret = 0, i; + if (priv->xmit_qdisc.enabled && + tx_cnt < priv->xmit_qdisc.num_tx_queues) + return -EINVAL; + if (netif_running(dev)) stmmac_release(dev);
@@ -7714,6 +7718,9 @@ int stmmac_reinit_queues(struct net_device *dev, u8 rx_cnt, u8 tx_cnt) priv->plat->rx_queues_to_use = rx_cnt; priv->plat->tx_queues_to_use = tx_cnt; + if (!priv->xmit_qdisc.enabled) + priv->xmit_qdisc.num_tx_queues = tx_cnt; + if (!netif_is_rxfh_configured(dev)) for (i = 0; i < ARRAY_SIZE(priv->rss.table); i++) priv->rss.table[i] = ethtool_rxfh_indir_default(i,
@@ -8025,6 +8032,9 @@ static int __stmmac_dvr_probe(struct device *device, ndev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT | NETDEV_XDP_ACT_XSK_ZEROCOPY; + /* Default qdisc num_tx_queues */ + priv->xmit_qdisc.num_tx_queues = priv->plat->tx_queues_to_use; + ret = stmmac_tc_init(priv, priv); if (!ret) { ndev->hw_features |= NETIF_F_HW_TC;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index 1aa80d51ab33..a7721b2eee96 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c@@ -1266,6 +1266,9 @@ static int stmmac_reset_tc_mqprio(struct net_device *ndev, { struct stmmac_priv *priv = netdev_priv(ndev); + priv->xmit_qdisc.num_tx_queues = priv->plat->tx_queues_to_use; + priv->xmit_qdisc.enabled = false; + netdev_reset_tc(ndev); netif_set_real_num_tx_queues(ndev, priv->plat->tx_queues_to_use);
@@ -1299,6 +1302,13 @@ static int tc_setup_dwmac510_mqprio(struct stmmac_priv *priv, ndev_prio_tc_map[i] = READ_ONCE(ndev->prio_tc_map[i]); for (i = 0; i < qopt->num_tc; i++) { + if (qopt->offset[i] + qopt->count[i] > + priv->plat->tx_queues_to_use) { + NL_SET_ERR_MSG_MOD(extack, + "Queues exceed hw TX queues"); + return -EINVAL; + } + tc_to_txq[i] = (struct netdev_tc_txq) { .count = qopt->count[i], .offset = qopt->offset[i],
@@ -1321,6 +1331,9 @@ static int tc_setup_dwmac510_mqprio(struct stmmac_priv *priv, if (err) goto error_reset_num_tx_queues; + priv->xmit_qdisc.num_tx_queues = num_tx_queues; + priv->xmit_qdisc.enabled = true; + return 0; error_reset_num_tx_queues:
--
2.55.0