Skip to content

Commit c8d2819

Browse files
xiaoleiwang123456pelwell
authored andcommitted
net: macb: Fix RX ring refill issue after link up
When the link goes down, the receive pipeline is cleared but the RX queue pointer register remains unchanged. This causes a critical issue where some RX ring entries may contain invalid addresses after link up. The problem manifests when: 1. An entry with an invalid address prevents rx_tail from advancing (gem_rx() checks rxused as 0) 2. No gap exists between rx_prepared_head and rx_tail from previous refill operations 3. gem_rx_refill() cannot refill entries because CIRC_SPACE() always returns 0 4. RSR register reports exception with value 0x7 5. The hardware detected that the buffer was unavailable. The DMA will reread the pointer each time it receives an end-of-frame signal until a valid pointer is found, but the software cannot fill it. This regression was introduced by commit 99537d5 which moved mog_init_rings() from macb_mac_link_up() to macb_open(), leaving the RX ring in an inconsistent state after link transitions. Fix this by: - Reinitializing RX rings on link up via mog_init_rings() - Adding full_refill atomic counter to force complete ring refill - Ensuring all entries are traversed and refilled after link up - Resetting rx_tail and rx_prepared_head to 0 Fixes: 99537d5 ("net: macb: Relocate mog_init_rings() callback from macb_mac_link_up() to macb_open()") Closes: #7200 (comment) Signed-off-by: Xiaolei Wang <xiaolei.wang@windriver.com>
1 parent 6e53895 commit c8d2819

File tree

2 files changed

+13
-3
lines changed

2 files changed

+13
-3
lines changed

drivers/net/ethernet/cadence/macb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,6 +1285,7 @@ struct macb_queue {
12851285
void *rx_buffers;
12861286
struct napi_struct napi_rx;
12871287
struct queue_stats stats;
1288+
atomic_t full_refill;
12881289
};
12891290

12901291
struct ethtool_rx_fs_item {

drivers/net/ethernet/cadence/macb_main.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -725,11 +725,18 @@ static void macb_mac_link_up(struct phylink_config *config,
725725
/* Initialize rings & buffers as clearing MACB_BIT(TE) in link down
726726
* cleared the pipeline and control registers.
727727
*/
728-
macb_init_buffers(bp);
729728

730729
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue)
730+
atomic_set(&queue->full_refill, -1);
731+
732+
bp->macbgem_ops.mog_init_rings(bp);
733+
macb_init_buffers(bp);
734+
735+
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
736+
atomic_set(&queue->full_refill, bp->rx_ring_size);
731737
queue_writel(queue, IER,
732738
bp->rx_intr_mask | MACB_TX_INT_FLAGS | MACB_BIT(HRESP));
739+
}
733740
}
734741

735742
macb_or_gem_writel(bp, NCFGR, ctrl);
@@ -1275,8 +1282,9 @@ static void gem_rx_refill(struct macb_queue *queue)
12751282
struct macb *bp = queue->bp;
12761283
struct macb_dma_desc *desc;
12771284

1278-
while (CIRC_SPACE(queue->rx_prepared_head, queue->rx_tail,
1279-
bp->rx_ring_size) > 0) {
1285+
while (atomic_dec_if_positive(&queue->full_refill) >= 0 ||
1286+
((CIRC_SPACE(queue->rx_prepared_head, queue->rx_tail, bp->rx_ring_size) > 0) &&
1287+
(atomic_read(&queue->full_refill) != -1))) {
12801288
entry = macb_rx_ring_wrap(bp, queue->rx_prepared_head);
12811289

12821290
/* Make hw descriptor updates visible to CPU */
@@ -1412,6 +1420,7 @@ static int gem_rx(struct macb_queue *queue, struct napi_struct *napi,
14121420
queue->stats.rx_dropped++;
14131421
break;
14141422
}
1423+
14151424
/* now everything is ready for receiving packet */
14161425
queue->rx_skbuff[entry] = NULL;
14171426
len = ctrl & bp->rx_frm_len_mask;

0 commit comments

Comments
 (0)