Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: macb: Fix tx/rx malfunction after phy link down and up

In commit 99537d5c476c ("net: macb: Relocate mog_init_rings() callback
from macb_mac_link_up() to macb_open()"), the mog_init_rings() callback
was moved from macb_mac_link_up() to macb_open() to resolve a deadlock
issue. However, this change introduced a tx/rx malfunction following
phy link down and up events. The issue arises from a mismatch between
the software queue->tx_head, queue->tx_tail, queue->rx_prepared_head,
and queue->rx_tail values and the hardware's internal tx/rx queue
pointers.

According to the Zynq UltraScale TRM [1], when tx/rx is disabled, the
internal tx queue pointer resets to the value in the tx queue base
address register, while the internal rx queue pointer remains unchanged.
The following is quoted from the Zynq UltraScale TRM:
When transmit is disabled, with bit [3] of the network control register
set low, the transmit-buffer queue pointer resets to point to the address
indicated by the transmit-buffer queue base address register. Disabling
receive does not have the same effect on the receive-buffer queue
pointer.

Additionally, there is no need to reset the RBQP and TBQP registers in a
phy event callback. Therefore, move macb_init_buffers() to macb_open().
In a phy link up event, the only required action is to reset the tx
software head and tail pointers to align with the hardware's behavior.

[1] https://docs.amd.com/v/u/en-US/ug1085-zynq-ultrascale-trm

Fixes: 99537d5c476c ("net: macb: Relocate mog_init_rings() callback from macb_mac_link_up() to macb_open()")
Signed-off-by: Kevin Hao <haokexin@gmail.com>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260208-macb-init-ring-v1-1-939a32c14635@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Kevin Hao and committed by
Paolo Abeni
bf9cf80c 6884028c

+5 -6
+5 -6
drivers/net/ethernet/cadence/macb_main.c
··· 705 705 if (rx_pause) 706 706 ctrl |= MACB_BIT(PAE); 707 707 708 - /* Initialize rings & buffers as clearing MACB_BIT(TE) in link down 709 - * cleared the pipeline and control registers. 710 - */ 711 - macb_init_buffers(bp); 712 - 713 - for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) 708 + for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) { 709 + queue->tx_head = 0; 710 + queue->tx_tail = 0; 714 711 queue_writel(queue, IER, 715 712 bp->rx_intr_mask | MACB_TX_INT_FLAGS | MACB_BIT(HRESP)); 713 + } 716 714 } 717 715 718 716 macb_or_gem_writel(bp, NCFGR, ctrl); ··· 2952 2954 } 2953 2955 2954 2956 bp->macbgem_ops.mog_init_rings(bp); 2957 + macb_init_buffers(bp); 2955 2958 2956 2959 for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) { 2957 2960 napi_enable(&queue->napi_rx);