Skip to content

Commit 50bd33f

Browse files
Jianpeng Changkuba-moo
authored andcommitted
net: enetc: fix the deadlock of enetc_mdio_lock
After applying the workaround for err050089, the LS1028A platform experiences RCU stalls on RT kernel. This issue is caused by the recursive acquisition of the read lock enetc_mdio_lock. Here list some of the call stacks identified under the enetc_poll path that may lead to a deadlock: enetc_poll -> enetc_lock_mdio -> enetc_clean_rx_ring OR napi_complete_done -> napi_gro_receive -> enetc_start_xmit -> enetc_lock_mdio -> enetc_map_tx_buffs -> enetc_unlock_mdio -> enetc_unlock_mdio After enetc_poll acquires the read lock, a higher-priority writer attempts to acquire the lock, causing preemption. The writer detects that a read lock is already held and is scheduled out. However, readers under enetc_poll cannot acquire the read lock again because a writer is already waiting, leading to a thread hang. Currently, the deadlock is avoided by adjusting enetc_lock_mdio to prevent recursive lock acquisition. Fixes: 6d36ecd ("net: enetc: take the MDIO lock only once per NAPI poll cycle") Signed-off-by: Jianpeng Chang <jianpeng.chang.cn@windriver.com> Acked-by: Wei Fang <wei.fang@nxp.com> Link: https://patch.msgid.link/20251015021427.180757-1-jianpeng.chang.cn@windriver.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 7f86445 commit 50bd33f

1 file changed

Lines changed: 21 additions & 4 deletions

File tree

  • drivers/net/ethernet/freescale/enetc

drivers/net/ethernet/freescale/enetc/enetc.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,6 +1595,8 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
15951595
/* next descriptor to process */
15961596
i = rx_ring->next_to_clean;
15971597

1598+
enetc_lock_mdio();
1599+
15981600
while (likely(rx_frm_cnt < work_limit)) {
15991601
union enetc_rx_bd *rxbd;
16001602
struct sk_buff *skb;
@@ -1630,14 +1632,18 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring,
16301632
rx_byte_cnt += skb->len + ETH_HLEN;
16311633
rx_frm_cnt++;
16321634

1635+
enetc_unlock_mdio();
16331636
napi_gro_receive(napi, skb);
1637+
enetc_lock_mdio();
16341638
}
16351639

16361640
rx_ring->next_to_clean = i;
16371641

16381642
rx_ring->stats.packets += rx_frm_cnt;
16391643
rx_ring->stats.bytes += rx_byte_cnt;
16401644

1645+
enetc_unlock_mdio();
1646+
16411647
return rx_frm_cnt;
16421648
}
16431649

@@ -1947,6 +1953,8 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
19471953
/* next descriptor to process */
19481954
i = rx_ring->next_to_clean;
19491955

1956+
enetc_lock_mdio();
1957+
19501958
while (likely(rx_frm_cnt < work_limit)) {
19511959
union enetc_rx_bd *rxbd, *orig_rxbd;
19521960
struct xdp_buff xdp_buff;
@@ -2010,7 +2018,9 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
20102018
*/
20112019
enetc_bulk_flip_buff(rx_ring, orig_i, i);
20122020

2021+
enetc_unlock_mdio();
20132022
napi_gro_receive(napi, skb);
2023+
enetc_lock_mdio();
20142024
break;
20152025
case XDP_TX:
20162026
tx_ring = priv->xdp_tx_ring[rx_ring->index];
@@ -2045,7 +2055,9 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
20452055
}
20462056
break;
20472057
case XDP_REDIRECT:
2058+
enetc_unlock_mdio();
20482059
err = xdp_do_redirect(rx_ring->ndev, &xdp_buff, prog);
2060+
enetc_lock_mdio();
20492061
if (unlikely(err)) {
20502062
enetc_xdp_drop(rx_ring, orig_i, i);
20512063
rx_ring->stats.xdp_redirect_failures++;
@@ -2065,8 +2077,11 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
20652077
rx_ring->stats.packets += rx_frm_cnt;
20662078
rx_ring->stats.bytes += rx_byte_cnt;
20672079

2068-
if (xdp_redirect_frm_cnt)
2080+
if (xdp_redirect_frm_cnt) {
2081+
enetc_unlock_mdio();
20692082
xdp_do_flush();
2083+
enetc_lock_mdio();
2084+
}
20702085

20712086
if (xdp_tx_frm_cnt)
20722087
enetc_update_tx_ring_tail(tx_ring);
@@ -2075,6 +2090,8 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring,
20752090
enetc_refill_rx_ring(rx_ring, enetc_bd_unused(rx_ring) -
20762091
rx_ring->xdp.xdp_tx_in_flight);
20772092

2093+
enetc_unlock_mdio();
2094+
20782095
return rx_frm_cnt;
20792096
}
20802097

@@ -2093,6 +2110,7 @@ static int enetc_poll(struct napi_struct *napi, int budget)
20932110
for (i = 0; i < v->count_tx_rings; i++)
20942111
if (!enetc_clean_tx_ring(&v->tx_ring[i], budget))
20952112
complete = false;
2113+
enetc_unlock_mdio();
20962114

20972115
prog = rx_ring->xdp.prog;
20982116
if (prog)
@@ -2104,10 +2122,8 @@ static int enetc_poll(struct napi_struct *napi, int budget)
21042122
if (work_done)
21052123
v->rx_napi_work = true;
21062124

2107-
if (!complete) {
2108-
enetc_unlock_mdio();
2125+
if (!complete)
21092126
return budget;
2110-
}
21112127

21122128
napi_complete_done(napi, work_done);
21132129

@@ -2116,6 +2132,7 @@ static int enetc_poll(struct napi_struct *napi, int budget)
21162132

21172133
v->rx_napi_work = false;
21182134

2135+
enetc_lock_mdio();
21192136
/* enable interrupts */
21202137
enetc_wr_reg_hot(v->rbier, ENETC_RBIER_RXTIE);
21212138

0 commit comments

Comments
 (0)