| From 507c4d749a1bbc3eb5c364dda61ac6bf95026cf1 Mon Sep 17 00:00:00 2001 |
| From: Phil Elwell <phil@raspberrypi.com> |
| Date: Fri, 25 Sep 2020 15:07:23 +0100 |
| Subject: [PATCH] net: bcmgenet: Reset RBUF on first open |
| |
| 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 |
| |
| Signed-off-by: Phil Elwell <phil@raspberrypi.com> |
| --- |
| drivers/net/ethernet/broadcom/genet/bcmgenet.c | 16 ++++++++++++---- |
| 1 file changed, 12 insertions(+), 4 deletions(-) |
| |
| --- 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 |
| } |
| |
| /* 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 b |
| 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_devi |
| |
| 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 |
| 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); |