* [PATCH net-next v5 0/3] net: stmmac: Introduce hw queue priority offload
@ 2026-10-06 10:46 Lorenzo Bianconi
2026-10-06 10:46 ` [PATCH net-next v5 1/3] net: stmmac: set real_num_tx_queues to max(offset + count) Lorenzo Bianconi
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Lorenzo Bianconi @ 2026-10-06 10:46 UTC (permalink / raw)
To: Maxime Chevallier, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue,
Vladimir Oltean, Furong Xu
Cc: Daniel Thompson, netdev, linux-stm32, linux-arm-kernel,
Lorenzo Bianconi, Davide Caratti
Implement the offload of the tc mqprio hw queue priority in the stmmac
driver. This feature requires the mqprio to be configured in channel
mode.
Do not overwrite real_num_tx_queues configured by the qdisc in
stmmac_hw_setup().
The misbehaviour has been reported by Shashank and the patch has been
tested on a Qualcomm RB3-Gen2 board.
---
Changes in v5:
- Move max num_tx_queue check from patch 3/3 to patch 2/3
- Check MTL_QUEUE_AVB queues in stmmac_reinit_queues().
- Update commit messages.
- Link to v4: https://lore.kernel.org/r/20261001-stmmac-mqprio-prio-offload-v4-0-a74610d7f1e5@oss.qualcomm.com
Changes in v4:
- Move real_num_tx_queues fix before mqprio offload patch in order to
allow easy backporting.
- Add patch 'net: stmmac: set real_num_tx_queues from max(offset +
count)' to fix the real_num_tx_queues configuration.
- Link to v3: https://lore.kernel.org/r/20260928-stmmac-mqprio-prio-offload-v3-0-abbe181f5024@oss.qualcomm.com
Changes in v3:
- Fix cbs overwriting removing mqprio qdisc configured in dcb mode.
- Return an error in stmmac_reinit_queues() if configured number of tx
queues is lower than xmit_qdisc.num_tx_queues and mqprio offloading is
enabled.
- Link to v2: https://lore.kernel.org/r/20260924-stmmac-mqprio-prio-offload-v2-0-fdd8b69efccf@oss.qualcomm.com
Changes in v2:
- Forbid cbs queue offload if mqprio is already enabled.
- SP requires 1:1 TC to TXQ map.
- Fix the real_num_tx_queue overwrite during device open.
- Require the qdisc to be configured in channel mode to enable hw queue
priority offload in order to not introduce any regression in the
previous driver behaviour.
- Link to v1: https://lore.kernel.org/r/20260918-stmmac-mqprio-prio-offload-v1-1-5328157fcb58@oss.qualcomm.com
---
Lorenzo Bianconi (3):
net: stmmac: set real_num_tx_queues to max(offset + count)
net: stmmac: align real_num_tx_queues to mqprio configuration
net: stmmac: add tc mqprio hw queue priority offload
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 9 ++
drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 45 +++++--
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 146 ++++++++++++++++++++--
4 files changed, 178 insertions(+), 24 deletions(-)
---
base-commit: 8b4e7209c842d8cb9516f1f5ef0a88aa2d8831a6
change-id: 20260918-stmmac-mqprio-prio-offload-3d82d87f7bc8
Best regards,
--
Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH net-next v5 1/3] net: stmmac: set real_num_tx_queues to max(offset + count)
2026-10-06 10:46 [PATCH net-next v5 0/3] net: stmmac: Introduce hw queue priority offload Lorenzo Bianconi
@ 2026-10-06 10:46 ` Lorenzo Bianconi
2026-10-06 10:46 ` [PATCH net-next v5 2/3] net: stmmac: align real_num_tx_queues to mqprio configuration Lorenzo Bianconi
` (2 subsequent siblings)
3 siblings, 0 replies; 8+ messages in thread
From: Lorenzo Bianconi @ 2026-10-06 10:46 UTC (permalink / raw)
To: Maxime Chevallier, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue,
Vladimir Oltean, Furong Xu
Cc: Daniel Thompson, netdev, linux-stm32, linux-arm-kernel,
Lorenzo Bianconi
tc_setup_dwmac510_mqprio() computes the number of real TX queues as the
sum of the per-TC queue counts. mqprio_validate_queue_counts() only
rejects out-of-bounds or overlapping ranges, so layouts with gaps or a
non-zero first offset are accepted, and in those cases the sum is smaller
than the highest queue referenced by the netdev TC map.
netif_set_real_num_tx_queues() then passes this too-small count to
netif_setup_tc(). However stmmac_set_ndev_tcs() has already zeroed
dev->prio_tc_map() through netdev_reset_tc(), so when netif_setup_tc()
runs every priority maps to TC0 and only the TC0 range is checked. A
layout whose TC0 range fits but where a later TC references a queue
beyond the new real_num_tx_queues is left with num_tc set and its TC map
pointing at queues that are no longer real, without any warning; only
when TC0 itself is out of range is the mapping disabled. The real
prio_tc_map is programmed later by the qdisc, after this call, so the
driver cannot rely on netif_setup_tc() to catch those cases.
Compute num_tx_queues as the maximum of offset[i] + count[i] instead of
the sum of the counts, so real_num_tx_queues always covers the highest
queue referenced by the TC map. This is a no-op for the contiguous
channel-mode layouts where offset[i] == i and count[i] == 1.
The issue has been reported by sashiko and the patch has been tested on
Qualcomm RB3-Gen2 board.
Fixes: 195e4f409a40 ("net: stmmac: support fp parameter of tc-mqprio")
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index 42a00446e9b4..1aa80d51ab33 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -1303,7 +1303,8 @@ static int tc_setup_dwmac510_mqprio(struct stmmac_priv *priv,
.count = qopt->count[i],
.offset = qopt->offset[i],
};
- num_tx_queues += qopt->count[i];
+ num_tx_queues = max(num_tx_queues,
+ qopt->offset[i] + qopt->count[i]);
}
err = stmmac_set_ndev_tcs(ndev, qopt->num_tc, tc_to_txq);
--
2.55.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH net-next v5 2/3] net: stmmac: align real_num_tx_queues to mqprio configuration
2026-10-06 10:46 [PATCH net-next v5 0/3] net: stmmac: Introduce hw queue priority offload Lorenzo Bianconi
2026-10-06 10:46 ` [PATCH net-next v5 1/3] net: stmmac: set real_num_tx_queues to max(offset + count) Lorenzo Bianconi
@ 2026-10-06 10:46 ` Lorenzo Bianconi
2026-10-06 10:46 ` [PATCH net-next v5 3/3] net: stmmac: add tc mqprio hw queue priority offload Lorenzo Bianconi
2026-10-06 10:49 ` [PATCH net-next v5 0/3] net: stmmac: Introduce " netdev-bot+sinfo
3 siblings, 0 replies; 8+ messages in thread
From: Lorenzo Bianconi @ 2026-10-06 10:46 UTC (permalink / raw)
To: Maxime Chevallier, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue,
Vladimir Oltean, Furong Xu
Cc: Daniel Thompson, netdev, linux-stm32, linux-arm-kernel,
Lorenzo Bianconi
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 <lorenzo.bianconi@oss.qualcomm.com>
---
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
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH net-next v5 3/3] net: stmmac: add tc mqprio hw queue priority offload
2026-10-06 10:46 [PATCH net-next v5 0/3] net: stmmac: Introduce hw queue priority offload Lorenzo Bianconi
2026-10-06 10:46 ` [PATCH net-next v5 1/3] net: stmmac: set real_num_tx_queues to max(offset + count) Lorenzo Bianconi
2026-10-06 10:46 ` [PATCH net-next v5 2/3] net: stmmac: align real_num_tx_queues to mqprio configuration Lorenzo Bianconi
@ 2026-10-06 10:46 ` Lorenzo Bianconi
2026-10-08 15:31 ` Daniel Thompson
2026-10-06 10:49 ` [PATCH net-next v5 0/3] net: stmmac: Introduce " netdev-bot+sinfo
3 siblings, 1 reply; 8+ messages in thread
From: Lorenzo Bianconi @ 2026-10-06 10:46 UTC (permalink / raw)
To: Maxime Chevallier, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue,
Vladimir Oltean, Furong Xu
Cc: Daniel Thompson, netdev, linux-stm32, linux-arm-kernel,
Davide Caratti, Lorenzo Bianconi
Implement the offload of the tc mqprio hw queue priority in the stmmac
driver. When the mqprio qdisc is configured in channel mode, the MTL TX
scheduler is switched to strict priority, and the PSTQX/PSTC priority
bitmask of each TX queue is programmed from the set of frame priorities
mapped to the owning traffic class (qopt->prio_tc_map).
The channel mode offload requires the DCB hw feature and a 1:1 TC to TX
queue mapping, with a single queue per TC. Configurations with AVB queues
are rejected, since forcing strict priority conflicts with the CBS
algorithm. The CBS offload is refused while the strict-priority scheduler
is active, and so is a channel count change that would enable an AVB
queue.
In the default DCB mode, only the netdev TC map and the FPE preemption
class mapping are offloaded, leaving the MTL scheduler and the per-queue
priorities to the device-tree configuration.
The num_tc bound against ARRAY_SIZE(tc_to_txq) is no longer needed: the
check that each TC's offset + count stays within plat->tx_queues_to_use
already bounds num_tc, because the TC ranges do not overlap and each one
spans at least one queue.
Reviewed-by: Davide Caratti <dcaratti@redhat.com>
Tested-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@oss.qualcomm.com>
---
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 3 +
drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 33 ++++--
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 134 ++++++++++++++++++++--
4 files changed, 148 insertions(+), 24 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 0052f2129297..40eab899027b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -302,7 +302,10 @@ struct stmmac_priv {
struct {
bool enabled;
+ u32 prio[MTL_MAX_TX_QUEUES];
+ bool prio_offload;
u32 num_tx_queues;
+ u8 algo;
} xmit_qdisc;
struct dma_features dma_cap;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
index c889204a7aa5..b6b5ef7c8fc4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
@@ -230,7 +230,7 @@ int dwmac5_fpe_map_preemption_class(struct net_device *ndev,
if (count == 1)
continue;
- if (priv->plat->tx_sched_algorithm == MTL_TX_ALGORITHM_SP) {
+ if (priv->xmit_qdisc.algo == MTL_TX_ALGORITHM_SP) {
NL_SET_ERR_MSG_MOD(extack, ALG_ERR_MSG);
return -EINVAL;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 9c03d21ebfcc..762ac86a9abb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -3535,17 +3535,11 @@ static void stmmac_mac_config_rx_queues_prio(struct stmmac_priv *priv)
*/
static void stmmac_mac_config_tx_queues_prio(struct stmmac_priv *priv)
{
- u8 tx_queues_count = priv->plat->tx_queues_to_use;
- u8 queue;
- u32 prio;
-
- for (queue = 0; queue < tx_queues_count; queue++) {
- if (!priv->plat->tx_queues_cfg[queue].use_prio)
- continue;
+ int i;
- prio = priv->plat->tx_queues_cfg[queue].prio;
- stmmac_tx_queue_prio(priv, priv->hw, prio, queue);
- }
+ for (i = 0; i < priv->plat->tx_queues_to_use; i++)
+ stmmac_tx_queue_prio(priv, priv->hw,
+ priv->xmit_qdisc.prio[i], i);
}
/**
@@ -3606,7 +3600,7 @@ static void stmmac_mtl_configuration(struct stmmac_priv *priv)
/* Configure MTL TX algorithms */
if (tx_queues_count > 1)
stmmac_prog_mtl_tx_algorithms(priv, priv->hw,
- priv->plat->tx_sched_algorithm);
+ priv->xmit_qdisc.algo);
/* Configure CBS in AVB TX queues */
if (tx_queues_count > 1)
@@ -7711,6 +7705,14 @@ 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);
@@ -7956,6 +7958,15 @@ static int __stmmac_dvr_probe(struct device *device,
priv->wol_irq = res->wol_irq;
priv->sfty_irq = res->sfty_irq;
+ /* Default xmit qdisc configuration */
+ for (i = 0; i < ARRAY_SIZE(priv->plat->tx_queues_cfg); i++) {
+ if (!priv->plat->tx_queues_cfg[i].use_prio)
+ continue;
+
+ priv->xmit_qdisc.prio[i] = priv->plat->tx_queues_cfg[i].prio;
+ }
+ priv->xmit_qdisc.algo = priv->plat->tx_sched_algorithm;
+
if (priv->plat->flags & STMMAC_FLAG_MULTI_MSI_EN) {
ret = stmmac_msi_init(priv, res);
if (ret)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index a7721b2eee96..ea1f97d6f0bd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -346,6 +346,9 @@ 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) {
@@ -1266,6 +1269,28 @@ static int stmmac_reset_tc_mqprio(struct net_device *ndev,
{
struct stmmac_priv *priv = netdev_priv(ndev);
+ if (priv->xmit_qdisc.prio_offload) {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(priv->plat->tx_queues_cfg); i++) {
+ u32 prio;
+
+ if (priv->plat->tx_queues_cfg[i].use_prio)
+ prio = priv->plat->tx_queues_cfg[i].prio;
+ else
+ prio = 0;
+
+ priv->xmit_qdisc.prio[i] = prio;
+ if (i < priv->plat->tx_queues_to_use)
+ stmmac_tx_queue_prio(priv, priv->hw, prio, i);
+ }
+
+ stmmac_prog_mtl_tx_algorithms(priv, priv->hw,
+ priv->plat->tx_sched_algorithm);
+ priv->xmit_qdisc.algo = priv->plat->tx_sched_algorithm;
+ priv->xmit_qdisc.prio_offload = false;
+ }
+
priv->xmit_qdisc.num_tx_queues = priv->plat->tx_queues_to_use;
priv->xmit_qdisc.enabled = false;
@@ -1275,6 +1300,83 @@ static int stmmac_reset_tc_mqprio(struct net_device *ndev,
return stmmac_fpe_map_preemption_class(priv, ndev, extack, 0);
}
+static void tc_mqprio_config_queue_prio(struct stmmac_priv *priv,
+ struct tc_mqprio_qopt *qopt)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(priv->plat->tx_queues_cfg); i++) {
+ u32 prio = 0;
+ int j;
+
+ for (j = 0; j < qopt->num_tc; j++) {
+ int p;
+
+ if (qopt->offset[j] != i)
+ continue;
+
+ /* The PSTQX/PSTC priority map is 8 bits wide, so only
+ * priorities 0-7 can be represented in hardware.
+ * Priorities 8-15 are handled in software by the
+ * kernel through the netdev prio_tc_map.
+ */
+ for (p = 0; p < 8; p++) {
+ if (qopt->prio_tc_map[p] == j)
+ prio |= BIT(p);
+ }
+ break;
+ }
+
+ priv->xmit_qdisc.prio[i] = prio;
+ if (i < priv->plat->tx_queues_to_use)
+ stmmac_tx_queue_prio(priv, priv->hw, prio, i);
+ }
+
+ stmmac_prog_mtl_tx_algorithms(priv, priv->hw, MTL_TX_ALGORITHM_SP);
+ priv->xmit_qdisc.algo = MTL_TX_ALGORITHM_SP;
+ priv->xmit_qdisc.prio_offload = true;
+}
+
+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;
+
+ if (!priv->dma_cap.dcben) {
+ NL_SET_ERR_MSG_MOD(mqprio->extack,
+ "hw DCB is required to offload mqprio");
+ 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
+ * mapping.
+ */
+ if (qopt->count[i] > 1 || qopt->offset[i] != i) {
+ NL_SET_ERR_MSG_MOD(mqprio->extack,
+ "SP requires 1:1 TXQ map");
+ return -EOPNOTSUPP;
+ }
+ }
+
+ return 0;
+}
+
static int tc_setup_dwmac510_mqprio(struct stmmac_priv *priv,
struct tc_mqprio_qopt_offload *mqprio)
{
@@ -1285,22 +1387,11 @@ static int tc_setup_dwmac510_mqprio(struct stmmac_priv *priv,
struct tc_mqprio_qopt *qopt = &mqprio->qopt;
struct net_device *ndev = priv->dev;
u8 ndev_prio_tc_map[TC_BITMASK + 1];
- int i, err, ndev_ntc;
+ int i, err, ndev_ntc, mode;
if (!qopt->num_tc)
return stmmac_reset_tc_mqprio(ndev, extack);
- if (qopt->num_tc > ARRAY_SIZE(tc_to_txq))
- return -EINVAL;
-
- /* save current tc values for reset */
- ndev_ntc = netdev_get_num_tc(ndev);
- for (i = 0; i < ARRAY_SIZE(ndev->tc_to_txq); i++)
- ndev_tc_to_txq[i].combined =
- READ_ONCE(ndev->tc_to_txq[i].combined);
- for (i = 0; i < ARRAY_SIZE(ndev_prio_tc_map); i++)
- 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) {
@@ -1317,6 +1408,22 @@ static int tc_setup_dwmac510_mqprio(struct stmmac_priv *priv,
qopt->offset[i] + qopt->count[i]);
}
+ mode = mqprio->flags & TC_MQPRIO_F_MODE ? mqprio->mode
+ : TC_MQPRIO_MODE_DCB;
+ if (mode == TC_MQPRIO_MODE_CHANNEL) {
+ err = tc_mqprio_validate_chan_mode(priv, mqprio);
+ if (err)
+ return err;
+ }
+
+ /* save current tc values for reset */
+ ndev_ntc = netdev_get_num_tc(ndev);
+ for (i = 0; i < ARRAY_SIZE(ndev->tc_to_txq); i++)
+ ndev_tc_to_txq[i].combined =
+ READ_ONCE(ndev->tc_to_txq[i].combined);
+ for (i = 0; i < ARRAY_SIZE(ndev_prio_tc_map); i++)
+ ndev_prio_tc_map[i] = READ_ONCE(ndev->prio_tc_map[i]);
+
err = stmmac_set_ndev_tcs(ndev, qopt->num_tc, tc_to_txq);
if (err)
goto error_reset_tc;
@@ -1331,6 +1438,9 @@ static int tc_setup_dwmac510_mqprio(struct stmmac_priv *priv,
if (err)
goto error_reset_num_tx_queues;
+ if (mode == TC_MQPRIO_MODE_CHANNEL)
+ tc_mqprio_config_queue_prio(priv, qopt);
+
priv->xmit_qdisc.num_tx_queues = num_tx_queues;
priv->xmit_qdisc.enabled = true;
--
2.55.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH net-next v5 0/3] net: stmmac: Introduce hw queue priority offload
2026-10-06 10:46 [PATCH net-next v5 0/3] net: stmmac: Introduce hw queue priority offload Lorenzo Bianconi
` (2 preceding siblings ...)
2026-10-06 10:46 ` [PATCH net-next v5 3/3] net: stmmac: add tc mqprio hw queue priority offload Lorenzo Bianconi
@ 2026-10-06 10:49 ` netdev-bot+sinfo
2026-10-06 12:21 ` Lorenzo Bianconi
3 siblings, 1 reply; 8+ messages in thread
From: netdev-bot+sinfo @ 2026-10-06 10:49 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: Maxime Chevallier, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue,
Vladimir Oltean, Furong Xu, Daniel Thompson, netdev, linux-stm32,
linux-arm-kernel, Davide Caratti
Hi!
This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:
- Whether the issue was actually triggered, or is only theoretical
(e.g. found by code inspection). If it was triggered please include
the symptoms, like the stack trace or error messages.
Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account. If the series needs another revision for
other reasons, please include the information in the commit messages
then.
The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH net-next v5 0/3] net: stmmac: Introduce hw queue priority offload
2026-10-06 10:49 ` [PATCH net-next v5 0/3] net: stmmac: Introduce " netdev-bot+sinfo
@ 2026-10-06 12:21 ` Lorenzo Bianconi
2026-10-06 16:18 ` Daniel Thompson
0 siblings, 1 reply; 8+ messages in thread
From: Lorenzo Bianconi @ 2026-10-06 12:21 UTC (permalink / raw)
To: netdev-bot+sinfo
Cc: Maxime Chevallier, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue,
Vladimir Oltean, Furong Xu, Daniel Thompson, netdev, linux-stm32,
linux-arm-kernel, Davide Caratti
[-- Attachment #1: Type: text/plain, Size: 826 bytes --]
> Hi!
>
> This is an automated message. This series looks like a fix, but its
> commit messages seem to be missing some information:
>
> - Whether the issue was actually triggered, or is only theoretical
> (e.g. found by code inspection). If it was triggered please include
> the symptoms, like the stack trace or error messages.
This is a theoretical issue found during code inspection.
>
> Please do not repost the series just to address the above. Instead,
> reply to this email with the missing information, so that reviewers
> can take it into account. If the series needs another revision for
> other reasons, please include the information in the commit messages
> then.
>
> The evaluation is done by an LLM so it may be wrong, if you think
> that is the case please reply and explain.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH net-next v5 0/3] net: stmmac: Introduce hw queue priority offload
2026-10-06 12:21 ` Lorenzo Bianconi
@ 2026-10-06 16:18 ` Daniel Thompson
0 siblings, 0 replies; 8+ messages in thread
From: Daniel Thompson @ 2026-10-06 16:18 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: netdev-bot+sinfo, Maxime Chevallier, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Coquelin,
Alexandre Torgue, Vladimir Oltean, Furong Xu, netdev, linux-stm32,
linux-arm-kernel, Davide Caratti
On Tue, Oct 06, 2026 at 02:21:28PM +0200, Lorenzo Bianconi wrote:
> > Hi!
> >
> > This is an automated message. This series looks like a fix, but its
> > commit messages seem to be missing some information:
> >
> > - Whether the issue was actually triggered, or is only theoretical
> > (e.g. found by code inspection). If it was triggered please include
> > the symptoms, like the stack trace or error messages.
>
> This is a theoretical issue found during code inspection.
I haven't triggered anything specific for the real_num_tx_queues changes
but the overall with/without mqprio offload changes can (and have) been
reproduced with netperf:
netperf -H 192.168.10.2 -s 1 -l 12 -y 7 -t UDP_STREAM -- -m 1472 & \
netperf -H 192.168.10.2 -s 2 -l 10 -y 5 -t UDP_STREAM -- -m 1472 & \
wait
With the patchset applied (and the traffic class 7 mapped to a higher
priority queue and TC 5) then the split of bandwidth massively favours
TC 7 (with a 2.5G link. TC 7 measure ~2G versus TC 5 at ~2M).
Without the patchset both streams get ~1G.
I guess FWIW the whole series is:
Tested-by: Daniel Thompson <daniel@riscstar.com>
Daniel.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH net-next v5 3/3] net: stmmac: add tc mqprio hw queue priority offload
2026-10-06 10:46 ` [PATCH net-next v5 3/3] net: stmmac: add tc mqprio hw queue priority offload Lorenzo Bianconi
@ 2026-10-08 15:31 ` Daniel Thompson
0 siblings, 0 replies; 8+ messages in thread
From: Daniel Thompson @ 2026-10-08 15:31 UTC (permalink / raw)
To: Lorenzo Bianconi
Cc: Maxime Chevallier, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue,
Vladimir Oltean, Furong Xu, netdev, linux-stm32, linux-arm-kernel,
Davide Caratti
On Tue, Oct 06, 2026 at 12:46:27PM +0200, Lorenzo Bianconi wrote:
> Implement the offload of the tc mqprio hw queue priority in the stmmac
> driver. When the mqprio qdisc is configured in channel mode, the MTL TX
> scheduler is switched to strict priority, and the PSTQX/PSTC priority
> bitmask of each TX queue is programmed from the set of frame priorities
> mapped to the owning traffic class (qopt->prio_tc_map).
>
> The channel mode offload requires the DCB hw feature and a 1:1 TC to TX
> queue mapping, with a single queue per TC. Configurations with AVB queues
> are rejected, since forcing strict priority conflicts with the CBS
> algorithm. The CBS offload is refused while the strict-priority scheduler
> is active, and so is a channel count change that would enable an AVB
> queue.
I don't think these CBS offload checks are necessary. It's quite reasonable
to mix strict priority on low priority queues with CBS on higher
priority queues.
In fact on the hardware I have (TC956x) the lower priority queues don't
implement CBS so mixing AVB and DCB queuing (whether SP or ETS) isn't
just reasonable, it's pretty much unavoidable when using CBS!
As a concrete example of combining mqprio and CBS, the following works well on
TC956x (when I tested an older version of your patch):
--- cut here ---
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@0 1@1 1@2 1@3 mode channel hw 1
# No CBS for TxQ1 means we can't offload this (h/ware stays in SP mode)
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
--- cut here ---
Daniel.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-10-08 15:31 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-06 10:46 [PATCH net-next v5 0/3] net: stmmac: Introduce hw queue priority offload Lorenzo Bianconi
2026-10-06 10:46 ` [PATCH net-next v5 1/3] net: stmmac: set real_num_tx_queues to max(offset + count) Lorenzo Bianconi
2026-10-06 10:46 ` [PATCH net-next v5 2/3] net: stmmac: align real_num_tx_queues to mqprio configuration Lorenzo Bianconi
2026-10-06 10:46 ` [PATCH net-next v5 3/3] net: stmmac: add tc mqprio hw queue priority offload Lorenzo Bianconi
2026-10-08 15:31 ` Daniel Thompson
2026-10-06 10:49 ` [PATCH net-next v5 0/3] net: stmmac: Introduce " netdev-bot+sinfo
2026-10-06 12:21 ` Lorenzo Bianconi
2026-10-06 16:18 ` Daniel Thompson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox