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 Signed-off-by: Nicolai Buchwitz --- 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