* [PATCH net v2 1/2] net: bcmgenet: cap the Tx queue threshold at the ring size
2026-11-09 21:53 [PATCH net v2 0/2] net: bcmgenet: fix tx stalls on 32 descriptor rings Nicolai Buchwitz
@ 2026-11-09 21:53 ` Nicolai Buchwitz
2026-11-09 21:53 ` [PATCH net v2 2/2] net: bcmgenet: flatten frames that cannot fit the ring Nicolai Buchwitz
2026-11-11 1:10 ` [PATCH net v2 0/2] net: bcmgenet: fix tx stalls on 32 descriptor rings patchwork-bot+netdevbpf
2 siblings, 0 replies; 5+ messages in thread
From: Nicolai Buchwitz @ 2026-11-09 21:53 UTC (permalink / raw)
To: Doug Berger, Florian Fainelli, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Justin Chen, Broadcom internal kernel review list,
Nikolay Aleksandrov, Jason Xing, netdev, linux-kernel,
Nicolai Buchwitz
A Tx queue stops when MAX_SKB_FRAGS + 1 or fewer descriptors are free and
wakes once there are more. Queues 1 to 4 hold 32 descriptors, so with
CONFIG_MAX_SKB_FRAGS at 31 they would need 33 to wake. As a result the
first packet stops the queue and it stays stopped:
eth0: NETDEV WATCHDOG: CPU: 0: transmit queue 3 timed out 2004 ms
eth0: NETDEV WATCHDOG: CPU: 1: transmit queue 4 timed out 2004 ms
On a Raspberry Pi CM4 only queue 0 carried traffic afterwards. The other
four counted an error on nearly every packet.
Fix this and cap the threshold at what the ring can free.
Fixes: 3948b05950fd ("net: introduce a config option to tweak MAX_SKB_FRAGS")
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de>
---
drivers/net/ethernet/broadcom/genet/bcmgenet.c | 6 ++++--
drivers/net/ethernet/broadcom/genet/bcmgenet.h | 1 +
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index 4d2be2a21ed1b..9049822012d13 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -2030,7 +2030,7 @@ static int bcmgenet_tx_poll(struct napi_struct *napi, int budget)
spin_lock(&ring->lock);
__bcmgenet_tx_reclaim(ring->priv->dev, ring);
- if (ring->free_bds > (MAX_SKB_FRAGS + 1)) {
+ if (ring->free_bds > ring->stop_thld) {
txq = netdev_get_tx_queue(ring->priv->dev, ring->index);
netif_tx_wake_queue(txq);
}
@@ -2235,7 +2235,7 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
netdev_tx_sent_queue(txq, GENET_CB(skb)->bytes_sent);
- if (ring->free_bds <= (MAX_SKB_FRAGS + 1))
+ if (ring->free_bds <= ring->stop_thld)
netif_tx_stop_queue(txq);
if (!netdev_xmit_more() || netif_xmit_stopped(txq))
@@ -2742,6 +2742,8 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv,
ring->index = index;
ring->cbs = priv->tx_cbs + start_ptr;
ring->size = size;
+ /* An empty ring must be able to wake the queue */
+ ring->stop_thld = min_t(unsigned int, MAX_SKB_FRAGS + 1, size - 1);
ring->clean_ptr = start_ptr;
ring->c_index = 0;
ring->free_bds = size;
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
index e48ce39d3e7c8..6ab3f73475550 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
@@ -546,6 +546,7 @@ struct bcmgenet_tx_ring {
unsigned int index; /* ring index */
struct enet_cb *cbs; /* tx ring buffer control block*/
unsigned int size; /* size of each tx ring */
+ unsigned int stop_thld; /* queue stops at this many free bds or fewer */
unsigned int clean_ptr; /* Tx ring clean pointer */
unsigned int c_index; /* last consumer index of each ring*/
unsigned int free_bds; /* # of free bds for each ring */
--
2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH net v2 2/2] net: bcmgenet: flatten frames that cannot fit the ring
2026-11-09 21:53 [PATCH net v2 0/2] net: bcmgenet: fix tx stalls on 32 descriptor rings Nicolai Buchwitz
2026-11-09 21:53 ` [PATCH net v2 1/2] net: bcmgenet: cap the Tx queue threshold at the ring size Nicolai Buchwitz
@ 2026-11-09 21:53 ` Nicolai Buchwitz
2026-11-09 22:14 ` Florian Fainelli
2026-11-11 1:10 ` [PATCH net v2 0/2] net: bcmgenet: fix tx stalls on 32 descriptor rings patchwork-bot+netdevbpf
2 siblings, 1 reply; 5+ messages in thread
From: Nicolai Buchwitz @ 2026-11-09 21:53 UTC (permalink / raw)
To: Doug Berger, Florian Fainelli, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Justin Chen, Broadcom internal kernel review list,
Nikolay Aleksandrov, Jason Xing, netdev, linux-kernel,
Nicolai Buchwitz
bcmgenet_xmit() wants one descriptor more than the frame needs. A 31
fragment frame needs 32 descriptors, so it is refused on a 32 descriptor
ring, even if the ring is empty.
As a result nothing is in flight which could wake the queue again. The
watchdog can only hand the same frame back, therefore the queue stays
stopped.
This needs CONFIG_MAX_SKB_FRAGS >= 31 and a sender which fragments that
finely, for example MSG_ZEROCOPY.
Linearize those frames instead.
Fixes: 3948b05950fd ("net: introduce a config option to tweak MAX_SKB_FRAGS")
Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de>
---
drivers/net/ethernet/broadcom/genet/bcmgenet.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index 9049822012d13..61f5a4c2f0cd9 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -2143,6 +2143,22 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
nr_frags = skb_shinfo(skb)->nr_frags;
+ /* The check below would always refuse this frame */
+ if (unlikely(nr_frags + 1 >= ring->size)) {
+ skb = skb_share_check(skb, GFP_ATOMIC);
+ if (skb && skb_linearize(skb)) {
+ dev_kfree_skb_any(skb);
+ skb = NULL;
+ }
+ if (!skb) {
+ spin_lock(&ring->lock);
+ BCMGENET_STATS64_INC((&ring->stats64), dropped);
+ ret = NETDEV_TX_OK;
+ goto out;
+ }
+ nr_frags = 0;
+ }
+
spin_lock(&ring->lock);
if (ring->free_bds <= (nr_frags + 1)) {
if (!netif_tx_queue_stopped(txq))
--
2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH net v2 2/2] net: bcmgenet: flatten frames that cannot fit the ring
2026-11-09 21:53 ` [PATCH net v2 2/2] net: bcmgenet: flatten frames that cannot fit the ring Nicolai Buchwitz
@ 2026-11-09 22:14 ` Florian Fainelli
0 siblings, 0 replies; 5+ messages in thread
From: Florian Fainelli @ 2026-11-09 22:14 UTC (permalink / raw)
To: Nicolai Buchwitz, Doug Berger, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Justin Chen, Broadcom internal kernel review list,
Nikolay Aleksandrov, Jason Xing, netdev, linux-kernel
On 11/9/26 13:53, Nicolai Buchwitz wrote:
> bcmgenet_xmit() wants one descriptor more than the frame needs. A 31
> fragment frame needs 32 descriptors, so it is refused on a 32 descriptor
> ring, even if the ring is empty.
>
> As a result nothing is in flight which could wake the queue again. The
> watchdog can only hand the same frame back, therefore the queue stays
> stopped.
>
> This needs CONFIG_MAX_SKB_FRAGS >= 31 and a sender which fragments that
> finely, for example MSG_ZEROCOPY.
>
> Linearize those frames instead.
>
> Fixes: 3948b05950fd ("net: introduce a config option to tweak MAX_SKB_FRAGS")
> Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
--
Florian
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net v2 0/2] net: bcmgenet: fix tx stalls on 32 descriptor rings
2026-11-09 21:53 [PATCH net v2 0/2] net: bcmgenet: fix tx stalls on 32 descriptor rings Nicolai Buchwitz
2026-11-09 21:53 ` [PATCH net v2 1/2] net: bcmgenet: cap the Tx queue threshold at the ring size Nicolai Buchwitz
2026-11-09 21:53 ` [PATCH net v2 2/2] net: bcmgenet: flatten frames that cannot fit the ring Nicolai Buchwitz
@ 2026-11-11 1:10 ` patchwork-bot+netdevbpf
2 siblings, 0 replies; 5+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-11-11 1:10 UTC (permalink / raw)
To: Nicolai Buchwitz
Cc: opendmb, florian.fainelli, andrew+netdev, davem, edumazet, kuba,
pabeni, justin.chen, bcm-kernel-feedback-list, razor,
kerneljasonxing, netdev, linux-kernel
Hello:
This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Mon, 09 Nov 2026 22:53:00 +0100 you wrote:
> Found this while fixing the clashiko findings on v6 of my MTU series. After
> those fixes this bug would be easier to hit. At the moment it needs a larger
> CONFIG_MAX_SKB_FRAGS than the default.
>
> Queues 1 to 4 hold 32 descriptors, which is less than the Tx path assumes
> in two places with CONFIG_MAX_SKB_FRAGS >= 31.
>
> [...]
Here is the summary with links:
- [net,v2,1/2] net: bcmgenet: cap the Tx queue threshold at the ring size
https://git.kernel.org/netdev/net-next/c/1e09af397bc7
- [net,v2,2/2] net: bcmgenet: flatten frames that cannot fit the ring
https://git.kernel.org/netdev/net-next/c/fbfd7cfd2019
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 5+ messages in thread