From 2420a7755665d50c7bbd0fefb13a36eb0457bcbd Mon Sep 17 00:00:00 2001 From: Markus Stockhausen Date: Fri, 5 Sep 2025 02:53:41 -0400 Subject: [PATCH] realtek: make NAPI polling thread safe At the end of RX NAPI polling the counter and mask registers are cleaned up. Although this might run in parallel there is no synchronization and the register modifications are some wild mix. RTL83xx enables only the interrupt of a single ring while RTL93xx just reactivates all interrupts (even for other NAPI threads). Make use of the driver lock and only modify the interrupt bits that the current thread owns. Signed-off-by: Markus Stockhausen Link: https://github.com/openwrt/openwrt/pull/19960 Signed-off-by: Robert Marko --- .../realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c | 5 ++++- .../realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c index 1ed3718cb33..d2d4d0bf7c8 100644 --- a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c +++ b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c @@ -1300,6 +1300,7 @@ static int rtl838x_poll_rx(struct napi_struct *napi, int budget) { struct rtl838x_rx_q *rx_q = container_of(napi, struct rtl838x_rx_q, napi); struct rtl838x_eth_priv *priv = rx_q->priv; + unsigned long flags; int ring = rx_q->id; int work_done = 0; @@ -1312,10 +1313,12 @@ static int rtl838x_poll_rx(struct napi_struct *napi, int budget) if (work_done < budget && napi_complete_done(napi, work_done)) { /* Re-enable rx interrupts */ + spin_lock_irqsave(&priv->lock, flags); if (priv->family_id == RTL9300_FAMILY_ID || priv->family_id == RTL9310_FAMILY_ID) - sw_w32(0xffffffff, priv->r->dma_if_intr_rx_done_msk); + sw_w32_mask(0, RTL93XX_DMA_IF_INTR_RX_MASK(ring), priv->r->dma_if_intr_rx_done_msk); else sw_w32_mask(0, RTL83XX_DMA_IF_INTR_RX_MASK(ring), priv->r->dma_if_intr_msk); + spin_unlock_irqrestore(&priv->lock, flags); } return work_done; diff --git a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h index 458718750cf..f1e4b176091 100644 --- a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h +++ b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h @@ -52,6 +52,7 @@ #define RTL83XX_DMA_IF_INTR_RX_DONE_MASK GENMASK(15, 8) #define RTL83XX_DMA_IF_INTR_RX_RUN_OUT_MASK GENMASK(7, 0) #define RTL83XX_DMA_IF_INTR_RX_MASK(ring) (BIT(ring) | BIT(ring + 8)) +#define RTL93XX_DMA_IF_INTR_RX_MASK(ring) (BIT(ring)) /* MAC address settings */ #define RTL838X_MAC (0xa9ec) -- 2.47.3