| b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | From 507c4d749a1bbc3eb5c364dda61ac6bf95026cf1 Mon Sep 17 00:00:00 2001 |
| 2 | From: Phil Elwell <phil@raspberrypi.com> |
| 3 | Date: Fri, 25 Sep 2020 15:07:23 +0100 |
| 4 | Subject: [PATCH] net: bcmgenet: Reset RBUF on first open |
| 5 | |
| 6 | If the RBUF logic is not reset when the kernel starts then there |
| 7 | may be some data left over from any network boot loader. If the |
| 8 | 64-byte packet headers are enabled then this can be fatal. |
| 9 | |
| 10 | Extend bcmgenet_dma_disable to do perform the reset, but not when |
| 11 | called from bcmgenet_resume in order to preserve a wake packet. |
| 12 | |
| 13 | N.B. This different handling of resume is just based on a hunch - |
| 14 | why else wouldn't one reset the RBUF as well as the TBUF? If this |
| 15 | isn't the case then it's easy to change the patch to make the RBUF |
| 16 | reset unconditional. |
| 17 | |
| 18 | See: https://github.com/raspberrypi/linux/issues/3850 |
| 19 | |
| 20 | Signed-off-by: Phil Elwell <phil@raspberrypi.com> |
| 21 | --- |
| 22 | drivers/net/ethernet/broadcom/genet/bcmgenet.c | 16 ++++++++++++---- |
| 23 | 1 file changed, 12 insertions(+), 4 deletions(-) |
| 24 | |
| 25 | --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c |
| 26 | +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c |
| 27 | @@ -2806,7 +2806,7 @@ static void bcmgenet_set_hw_addr(struct |
| 28 | } |
| 29 | |
| 30 | /* Returns a reusable dma control register value */ |
| 31 | -static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv) |
| 32 | +static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv, bool flush_rx) |
| 33 | { |
| 34 | unsigned int i; |
| 35 | u32 reg; |
| 36 | @@ -2831,6 +2831,14 @@ static u32 bcmgenet_dma_disable(struct b |
| 37 | udelay(10); |
| 38 | bcmgenet_umac_writel(priv, 0, UMAC_TX_FLUSH); |
| 39 | |
| 40 | + if (flush_rx) { |
| 41 | + reg = bcmgenet_rbuf_ctrl_get(priv); |
| 42 | + bcmgenet_rbuf_ctrl_set(priv, reg | BIT(0)); |
| 43 | + udelay(10); |
| 44 | + bcmgenet_rbuf_ctrl_set(priv, reg); |
| 45 | + udelay(10); |
| 46 | + } |
| 47 | + |
| 48 | return dma_ctrl; |
| 49 | } |
| 50 | |
| 51 | @@ -2926,8 +2934,8 @@ static int bcmgenet_open(struct net_devi |
| 52 | |
| 53 | bcmgenet_set_hw_addr(priv, dev->dev_addr); |
| 54 | |
| 55 | - /* Disable RX/TX DMA and flush TX queues */ |
| 56 | - dma_ctrl = bcmgenet_dma_disable(priv); |
| 57 | + /* Disable RX/TX DMA and flush TX and RX queues */ |
| 58 | + dma_ctrl = bcmgenet_dma_disable(priv, true); |
| 59 | |
| 60 | /* Reinitialize TDMA and RDMA and SW housekeeping */ |
| 61 | ret = bcmgenet_init_dma(priv); |
| 62 | @@ -3682,7 +3690,7 @@ static int bcmgenet_resume(struct device |
| 63 | bcmgenet_power_up(priv, GENET_POWER_WOL_MAGIC); |
| 64 | |
| 65 | /* Disable RX/TX DMA and flush TX queues */ |
| 66 | - dma_ctrl = bcmgenet_dma_disable(priv); |
| 67 | + dma_ctrl = bcmgenet_dma_disable(priv, false); |
| 68 | |
| 69 | /* Reinitialize TDMA and RDMA and SW housekeeping */ |
| 70 | ret = bcmgenet_init_dma(priv); |