aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux
diff options
context:
space:
mode:
authorBirger Koblitz <mail@birger-koblitz.de>2022-02-18 12:01:53 +0100
committerDaniel Golle <daniel@makrotopia.org>2022-02-18 12:35:03 +0000
commit4d8020072ee291fe4e7b751e2c1490830932bcc4 (patch)
treeab678ccae91f44a27034136aed99a6faf182f99a /target/linux
parente9e61d76fd5227f175b41f2d39e6c26cb3133524 (diff)
downloadupstream-4d8020072ee291fe4e7b751e2c1490830932bcc4.tar.gz
upstream-4d8020072ee291fe4e7b751e2c1490830932bcc4.tar.bz2
upstream-4d8020072ee291fe4e7b751e2c1490830932bcc4.zip
realtek: fix locking bug in rtl838x_hw_receive()
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 <bjorn@mork.no> Signed-off-by: Birger Koblitz <mail@birger-koblitz.de>
Diffstat (limited to 'target/linux')
-rw-r--r--target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c7
1 files 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 ab4a03550b..cf6aabc614 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;
}