]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
realtek: make NAPI polling thread safe 19960/head
authorMarkus Stockhausen <markus.stockhausen@gmx.de>
Fri, 5 Sep 2025 06:53:41 +0000 (02:53 -0400)
committerRobert Marko <robimarko@gmail.com>
Sun, 7 Sep 2025 09:36:01 +0000 (11:36 +0200)
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 <markus.stockhausen@gmx.de>
Link: https://github.com/openwrt/openwrt/pull/19960
Signed-off-by: Robert Marko <robimarko@gmail.com>
target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c
target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h

index 1ed3718cb3376f2b2e771495539fc90463c84899..d2d4d0bf7c8f57bc8c31dd66060984516e79a882 100644 (file)
@@ -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;
index 458718750cf42cb8365727dafb8241ef3986e6dc..f1e4b1760918ae80fecb93436b11304b0d8da706 100644 (file)
@@ -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)