A Locking bug in the packet receive path was introduced with PR
#4973. The following patch prevents the driver from locking
after a few minutes with an endless flow of

[ 1434.185085] rtl838x-eth 1b00a300.ethernet eth0: Ring contention: r: 0, last 
a28000f4, cur a28000f8
[ 1434.208971] rtl838x-eth 1b00a300.ethernet eth0: Ring contention: r: 0, last 
a28000f4, cur a28000fc
[ 1434.794800] rtl838x-eth 1b00a300.ethernet eth0: Ring contention: r: 0, last 
a28000f4, cur a28000fc
[ 1435.049187] rtl838x-eth 1b00a300.ethernet eth0: Ring contention: r: 0, last 
a28000f4, cur a28000fc

Signed-off-by: Bjørn Mork <bj...@mork.no>
Signed-off-by: Birger Koblitz <m...@birger-koblitz.de>
---
 .../realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c  | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c 
b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c
index ab4a03550bd8..cf6aabc6142f 100644
--- a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c
+++ b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c
@@ -1254,8 +1254,9 @@ static int rtl838x_hw_receive(struct net_device *dev, int 
r, int budget)
        bool dsa = netdev_uses_dsa(dev);
        struct dsa_tag tag;

-       last = (u32 *)KSEG1ADDR(sw_r32(priv->r->dma_if_rx_cur + r * 4));
        pr_debug("---------------------------------------------------------- RX 
- %d\n", r);
+       spin_lock_irqsave(&priv->lock, flags);
+       last = (u32 *)KSEG1ADDR(sw_r32(priv->r->dma_if_rx_cur + r * 4));

        do {
                if ((ring->rx_r[r][ring->c_rx[r]] & 0x1)) {
@@ -1329,7 +1330,6 @@ static int rtl838x_hw_receive(struct net_device *dev, int 
r, int budget)
                }

                /* Reset header structure */
-               spin_lock_irqsave(&priv->lock, flags);
                memset(h, 0, sizeof(struct p_hdr));
                h->buf = data;
                h->size = RING_BUFFER;
@@ -1338,12 +1338,13 @@ static int rtl838x_hw_receive(struct net_device *dev, 
int r, int budget)
                        | (ring->c_rx[r] == (priv->rxringlen - 1) ? WRAP : 0x1);
                ring->c_rx[r] = (ring->c_rx[r] + 1) % priv->rxringlen;
                last = (u32 *)KSEG1ADDR(sw_r32(priv->r->dma_if_rx_cur + r * 4));
-               spin_unlock_irqrestore(&priv->lock, flags);
        } while (&ring->rx_r[r][ring->c_rx[r]] != last && work_done < budget);

        // Update counters
        priv->r->update_cntr(r, 0);

+       spin_unlock_irqrestore(&priv->lock, flags);
+
        return work_done;
 }

-- 
2.30.2


_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to