| From a719908aaf96d0a9050a675a093a46862e9df5e2 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 1 Apr 2024 13:09:33 +0200 |
| Subject: net: bcmgenet: Reset RBUF on first open |
| |
| From: Phil Elwell <phil@raspberrypi.com> |
| |
| [ Upstream commit 0a6380cb4c6b5c1d6dad226ba3130f9090f0ccea ] |
| |
| If the RBUF logic is not reset when the kernel starts then there |
| may be some data left over from any network boot loader. If the |
| 64-byte packet headers are enabled then this can be fatal. |
| |
| Extend bcmgenet_dma_disable to do perform the reset, but not when |
| called from bcmgenet_resume in order to preserve a wake packet. |
| |
| N.B. This different handling of resume is just based on a hunch - |
| why else wouldn't one reset the RBUF as well as the TBUF? If this |
| isn't the case then it's easy to change the patch to make the RBUF |
| reset unconditional. |
| |
| See: https://github.com/raspberrypi/linux/issues/3850 |
| See: https://github.com/raspberrypi/firmware/issues/1882 |
| |
| Signed-off-by: Phil Elwell <phil@raspberrypi.com> |
| Signed-off-by: Maarten Vanraes <maarten@rmail.be> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/net/ethernet/broadcom/genet/bcmgenet.c | 16 ++++++++++++---- |
| 1 file changed, 12 insertions(+), 4 deletions(-) |
| |
| diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c |
| index 8bbc5dcf8cb43..9fded8a862d46 100644 |
| --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c |
| +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c |
| @@ -2806,7 +2806,7 @@ static void bcmgenet_set_hw_addr(struct bcmgenet_priv *priv, |
| } |
| |
| /* Returns a reusable dma control register value */ |
| -static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv) |
| +static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv, bool flush_rx) |
| { |
| unsigned int i; |
| u32 reg; |
| @@ -2831,6 +2831,14 @@ static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv) |
| udelay(10); |
| bcmgenet_umac_writel(priv, 0, UMAC_TX_FLUSH); |
| |
| + if (flush_rx) { |
| + reg = bcmgenet_rbuf_ctrl_get(priv); |
| + bcmgenet_rbuf_ctrl_set(priv, reg | BIT(0)); |
| + udelay(10); |
| + bcmgenet_rbuf_ctrl_set(priv, reg); |
| + udelay(10); |
| + } |
| + |
| return dma_ctrl; |
| } |
| |
| @@ -2926,8 +2934,8 @@ static int bcmgenet_open(struct net_device *dev) |
| |
| bcmgenet_set_hw_addr(priv, dev->dev_addr); |
| |
| - /* Disable RX/TX DMA and flush TX queues */ |
| - dma_ctrl = bcmgenet_dma_disable(priv); |
| + /* Disable RX/TX DMA and flush TX and RX queues */ |
| + dma_ctrl = bcmgenet_dma_disable(priv, true); |
| |
| /* Reinitialize TDMA and RDMA and SW housekeeping */ |
| ret = bcmgenet_init_dma(priv); |
| @@ -3682,7 +3690,7 @@ static int bcmgenet_resume(struct device *d) |
| bcmgenet_power_up(priv, GENET_POWER_WOL_MAGIC); |
| |
| /* Disable RX/TX DMA and flush TX queues */ |
| - dma_ctrl = bcmgenet_dma_disable(priv); |
| + dma_ctrl = bcmgenet_dma_disable(priv, false); |
| |
| /* Reinitialize TDMA and RDMA and SW housekeeping */ |
| ret = bcmgenet_init_dma(priv); |
| -- |
| 2.43.0 |
| |