Commit 8832e579 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net-bcmgenet-fix-queue-lock-up'

Justin Chen says:

====================
net: bcmgenet: fix queue lock up

We have been seeing reports of logs like this.
[   41.761198] bcmgenet 1001300000.ethernet eth0: NETDEV WATCHDOG: CPU: 0: transmit queue 2 timed out 10039 ms
[   43.745198] bcmgenet 1001300000.ethernet eth0: NETDEV WATCHDOG: CPU: 0: transmit queue 2 timed out 12023 ms
[   45.729198] bcmgenet 1001300000.ethernet eth0: NETDEV WATCHDOG: CPU: 0: transmit queue 2 timed out 14007 ms

We have two issues. The persistent queue timeouts and the eventual
lock up of the entire transmit.

We address the lock up issue first. The queue timeouts are due to
a fundamental design issue not a bug perse. Timeouts still persist,
but we should no longer lock up.
====================

Link: https://patch.msgid.link/20260406175756.134567-1-justin.chen@broadcom.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents b02e3c4c 5393b2b5
Loading
Loading
Loading
Loading
+14 −16
Original line number Diff line number Diff line
@@ -1819,15 +1819,15 @@ static struct enet_cb *bcmgenet_put_txcb(struct bcmgenet_priv *priv,
{
	struct enet_cb *tx_cb_ptr;

	tx_cb_ptr = ring->cbs;
	tx_cb_ptr += ring->write_ptr - ring->cb_ptr;

	/* Rewinding local write pointer */
	if (ring->write_ptr == ring->cb_ptr)
		ring->write_ptr = ring->end_ptr;
	else
		ring->write_ptr--;

	tx_cb_ptr = ring->cbs;
	tx_cb_ptr += ring->write_ptr - ring->cb_ptr;

	return tx_cb_ptr;
}

@@ -1985,6 +1985,7 @@ static unsigned int bcmgenet_tx_reclaim(struct net_device *dev,
		drop = (ring->prod_index - ring->c_index) & DMA_C_INDEX_MASK;
		released += drop;
		ring->prod_index = ring->c_index & DMA_C_INDEX_MASK;
		ring->free_bds += drop;
		while (drop--) {
			cb_ptr = bcmgenet_put_txcb(priv, ring);
			skb = cb_ptr->skb;
@@ -1996,6 +1997,7 @@ static unsigned int bcmgenet_tx_reclaim(struct net_device *dev,
		}
		if (skb)
			dev_consume_skb_any(skb);
		netdev_tx_reset_queue(netdev_get_tx_queue(dev, ring->index));
		bcmgenet_tdma_ring_writel(priv, ring->index,
					  ring->prod_index, TDMA_PROD_INDEX);
		wr_ptr = ring->write_ptr * WORDS_PER_BD(priv);
@@ -3475,27 +3477,23 @@ static void bcmgenet_dump_tx_queue(struct bcmgenet_tx_ring *ring)
static void bcmgenet_timeout(struct net_device *dev, unsigned int txqueue)
{
	struct bcmgenet_priv *priv = netdev_priv(dev);
	u32 int1_enable = 0;
	unsigned int q;
	struct bcmgenet_tx_ring *ring = &priv->tx_rings[txqueue];
	struct netdev_queue *txq = netdev_get_tx_queue(dev, txqueue);

	netif_dbg(priv, tx_err, dev, "bcmgenet_timeout\n");

	for (q = 0; q <= priv->hw_params->tx_queues; q++)
		bcmgenet_dump_tx_queue(&priv->tx_rings[q]);
	bcmgenet_dump_tx_queue(ring);

	bcmgenet_tx_reclaim_all(dev);
	bcmgenet_tx_reclaim(dev, ring, true);

	for (q = 0; q <= priv->hw_params->tx_queues; q++)
		int1_enable |= (1 << q);
	/* Re-enable the TX interrupt for this ring */
	bcmgenet_intrl2_1_writel(priv, 1 << txqueue, INTRL2_CPU_MASK_CLEAR);

	/* Re-enable TX interrupts if disabled */
	bcmgenet_intrl2_1_writel(priv, int1_enable, INTRL2_CPU_MASK_CLEAR);
	txq_trans_cond_update(txq);

	netif_trans_update(dev);
	BCMGENET_STATS64_INC((&ring->stats64), errors);

	BCMGENET_STATS64_INC((&priv->tx_rings[txqueue].stats64), errors);

	netif_tx_wake_all_queues(dev);
	netif_tx_wake_queue(txq);
}

#define MAX_MDF_FILTER	17