[PATCH] bcmgenet: fix DMA buffer management
Jason Wessel
jason.wessel at windriver.com
Thu Jul 16 14:02:12 CEST 2020
On 7/9/20 3:11 AM, etienne.duble at gmail.com wrote:
> From: Etienne Dublé <etienne.duble at imag.fr>
>
> This commit fixes a serious issue occuring when several network
> commands are run on a raspberry pi 4 board: for instance a "dhcp"
> command and then one or several "tftp" commands. In this case,
> packet recv callbacks were called several times on the same packets,
> and send function was failing most of the time.
>
> note: if the boot procedure is made of a single network
> command, the issue is not visible.
>
> The issue is related to management of the packet ring buffers
> (producer / consumer) and DMA.
> Each time a packet is received, the ethernet device stores it
> in the buffer and increments an index called RDMA_PROD_INDEX.
> Each time the driver outputs a received packet, it increments
> another index called RDMA_CONS_INDEX.
>
> Between each pair of network commands, as part of the driver
> 'start' function, previous code tried to reset both RDMA_CONS_INDEX
> and RDMA_PROD_INDEX to 0. But RDMA_PROD_INDEX cannot be written from
> driver side, thus its value was actually not updated, and only
> RDMA_CONS_INDEX was reset to 0. This was resulting in a major
> synchronization issue between the driver and the device. Most
> visible bahavior was that the driver seemed to receive again the
> packets from the previous commands (e.g. DHCP response packets
> "received" again when performing the first TFTP command).
>
> This fix consists in setting RDMA_CONS_INDEX to the same
> value as RDMA_PROD_INDEX, when resetting the driver.
>
> The same kind of fix was needed on the TX side, and a few variables
> had to be reset accordingly (c_index, tx_index, rx_index).
While there is some kind of problem with the driver, because I too
have observed a problem with multiple requests timing out or failing,
this patch makes the problem much worse. I was only able to complete
a single tftp request.
In my case I am using a static IP address and serverip.
Also your patch was missing the sign-off line. Please consider
running your patches through scripts/checkpatch.pl.
Cheers,
Jason.
> ---
> drivers/net/bcmgenet.c | 15 +++++++--------
> 1 file changed, 7 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/net/bcmgenet.c b/drivers/net/bcmgenet.c
> index 11b6148ab6..a4facfd63f 100644
> --- a/drivers/net/bcmgenet.c
> +++ b/drivers/net/bcmgenet.c
> @@ -378,8 +378,6 @@ static void rx_descs_init(struct bcmgenet_eth_priv *priv)
> u32 len_stat, i;
> void *desc_base = priv->rx_desc_base;
>
> - priv->c_index = 0;
> -
> len_stat = (RX_BUF_LENGTH << DMA_BUFLENGTH_SHIFT) | DMA_OWN;
>
> for (i = 0; i < RX_DESCS; i++) {
> @@ -403,8 +401,10 @@ static void rx_ring_init(struct bcmgenet_eth_priv *priv)
> writel(RX_DESCS * DMA_DESC_SIZE / 4 - 1,
> priv->mac_reg + RDMA_RING_REG_BASE + DMA_END_ADDR);
>
> - writel(0x0, priv->mac_reg + RDMA_PROD_INDEX);
> - writel(0x0, priv->mac_reg + RDMA_CONS_INDEX);
> + /* cannot init RDMA_PROD_INDEX to 0, so align RDMA_CONS_INDEX on it instead */
> + priv->c_index = readl(priv->mac_reg + RDMA_PROD_INDEX);
> + writel(priv->c_index, priv->mac_reg + RDMA_CONS_INDEX);
> + priv->rx_index = priv->c_index;
> writel((RX_DESCS << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH,
> priv->mac_reg + RDMA_RING_REG_BASE + DMA_RING_BUF_SIZE);
> writel(DMA_FC_THRESH_VALUE, priv->mac_reg + RDMA_XON_XOFF_THRESH);
> @@ -421,8 +421,9 @@ static void tx_ring_init(struct bcmgenet_eth_priv *priv)
> writel(0x0, priv->mac_reg + TDMA_WRITE_PTR);
> writel(TX_DESCS * DMA_DESC_SIZE / 4 - 1,
> priv->mac_reg + TDMA_RING_REG_BASE + DMA_END_ADDR);
> - writel(0x0, priv->mac_reg + TDMA_PROD_INDEX);
> - writel(0x0, priv->mac_reg + TDMA_CONS_INDEX);
> + /* cannot init TDMA_CONS_INDEX to 0, so align TDMA_PROD_INDEX on it instead */
> + priv->tx_index = readl(priv->mac_reg + TDMA_CONS_INDEX);
> + writel(priv->tx_index, priv->mac_reg + TDMA_PROD_INDEX);
> writel(0x1, priv->mac_reg + TDMA_RING_REG_BASE + DMA_MBUF_DONE_THRESH);
> writel(0x0, priv->mac_reg + TDMA_FLOW_PERIOD);
> writel((TX_DESCS << DMA_RING_SIZE_SHIFT) | RX_BUF_LENGTH,
> @@ -469,8 +470,6 @@ static int bcmgenet_gmac_eth_start(struct udevice *dev)
>
> priv->tx_desc_base = priv->mac_reg + GENET_TX_OFF;
> priv->rx_desc_base = priv->mac_reg + GENET_RX_OFF;
> - priv->tx_index = 0x0;
> - priv->rx_index = 0x0;
>
> bcmgenet_umac_reset(priv);
>
>
More information about the U-Boot
mailing list