[PATCH net 3/3] net: mvneta: serve the TX queues in weighted round robin
From: Josef Schlehofer
Date: Mon Nov 02 2026 - 06:32:48 EST
Under load, some TX queues get no service at all. With four TCP streams
on a 100 Mbit/s link, up to three streams sent nothing for 20 seconds.
The TX queue arbiter is left at its reset default, which serves all
queues in fixed priority. The stack spreads the flows over the queues,
so a busy queue starves the others.
Give the TX queues the same WRR weight and clear the fixed priority.
Like the Marvell reference driver, use the smallest weight that is
larger than the largest packet.
The mqprio offload never configured the TX scheduling, so its traffic
classes lose the fixed priority of the reset default as well.
Tested on a Turris Omnia (Armada 385). With this patch each busy TX
queue gets an equal share of the link and no stream stalls.
Fixes: ee40a116ebf1 ("net: mvneta: fix improper tx queue usage in mvneta_tx()")
Signed-off-by: Josef Schlehofer <pepe.schlehofer@xxxxxxxxx>
---
drivers/net/ethernet/marvell/mvneta.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 79711a117c39..75d46349df37 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -253,6 +253,7 @@
#define MVNETA_TXQ_CMD1_REG 0x3e00
#define MVNETA_TXQ_CMD1_BW_LIM_SEL_V1 BIT(3)
#define MVNETA_TXQ_CMD1_BW_LIM_EN BIT(0)
+#define MVNETA_TXQ_FIXED_PRIO_REG 0x3e04
#define MVNETA_REFILL_NUM_CLK_REG 0x3e08
#define MVNETA_REFILL_MAX_NUM_CLK 0x0000ffff
#define MVNETA_TX_MTU 0x3e0c
@@ -264,6 +265,8 @@
#define MVNETA_TXQ_BUCKET_REFILL_VALUE_MAX 0x0007ffff
#define MVNETA_TXQ_TOKEN_SIZE_REG(q) (0x3e40 + ((q) << 2))
#define MVNETA_TXQ_TOKEN_SIZE_MAX 0x7fffffff
+#define MVNETA_TXQ_WRR_ARB_REG(q) (0x3e80 + ((q) << 2))
+#define MVNETA_TXQ_WRR_WEIGHT_MASK 0xff
/* The values of the bucket refill base period and refill period are taken from
* the reference manual, and adds up to a base resolution of 10Kbps. This allows
@@ -1629,6 +1632,24 @@ static void mvneta_txq_max_tx_size_set(struct mvneta_port *pp, int max_tx_size)
}
}
+/* With the default fixed priority, a busy queue starves the others */
+static void mvneta_txq_wrr_set(struct mvneta_port *pp, int max_tx_size)
+{
+ /* In units of 256 bytes, must exceed the largest packet */
+ u32 weight = max_tx_size / 256 + 1;
+ int queue;
+ u32 val;
+
+ for (queue = 0; queue < txq_number; queue++) {
+ val = mvreg_read(pp, MVNETA_TXQ_WRR_ARB_REG(queue));
+ val &= ~MVNETA_TXQ_WRR_WEIGHT_MASK;
+ val |= weight;
+ mvreg_write(pp, MVNETA_TXQ_WRR_ARB_REG(queue), val);
+ }
+
+ mvreg_write(pp, MVNETA_TXQ_FIXED_PRIO_REG, 0);
+}
+
/* Set unicast address */
static void mvneta_set_ucast_addr(struct mvneta_port *pp, u8 last_nibble,
int queue)
@@ -3760,6 +3781,7 @@ static void mvneta_start_dev(struct mvneta_port *pp)
mvneta_max_rx_size_set(pp, pp->pkt_size);
mvneta_txq_max_tx_size_set(pp, pp->pkt_size);
+ mvneta_txq_wrr_set(pp, pp->pkt_size);
/* start the Rx/Tx activity */
mvneta_port_enable(pp);
--
2.54.0 (Apple Git-157)