[PATCH net v2 2/2] net: bcmgenet: flatten frames that cannot fit the ring

From: Nicolai Buchwitz

Date: Mon Nov 09 2026 - 16:55:34 EST


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@xxxxxxxxxxx>
---
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