[PATCH net v2 4/9] net: axienet: add missing memory barriers

Radhey Shyam Pandey radheys at xilinx.com
Thu Jan 13 04:09:41 PST 2022


> -----Original Message-----
> From: Robert Hancock <robert.hancock at calian.com>
> Sent: Wednesday, January 12, 2022 11:07 PM
> To: netdev at vger.kernel.org
> Cc: Radhey Shyam Pandey <radheys at xilinx.com>; davem at davemloft.net;
> kuba at kernel.org; linux-arm-kernel at lists.infradead.org; Michal Simek
> <michals at xilinx.com>; ariane.keller at tik.ee.ethz.ch; daniel at iogearbox.net;
> Robert Hancock <robert.hancock at calian.com>
> Subject: [PATCH net v2 4/9] net: axienet: add missing memory barriers
> 
> This driver was missing some required memory barriers:
> 
> Use dma_rmb to ensure we see all updates to the descriptor after we see that
> an entry has been completed.
> 
> Use wmb and rmb to avoid stale descriptor status between the TX path and TX
> complete IRQ path.
> 
> Fixes: 8a3b7a252dca9 ("drivers/net/ethernet/xilinx: added Xilinx AXI Ethernet
> driver")
> Signed-off-by: Robert Hancock <robert.hancock at calian.com>
> ---
>  drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> index f4ae035bed35..de8f85175a6c 100644
> --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> @@ -632,6 +632,8 @@ static int axienet_free_tx_chain(struct net_device
> *ndev, u32 first_bd,
>  		if (nr_bds == -1 && !(status &
> XAXIDMA_BD_STS_COMPLETE_MASK))
>  			break;
> 
> +		/* Ensure we see complete descriptor update */
> +		dma_rmb();
>  		phys = desc_get_phys_addr(lp, cur_p);
>  		dma_unmap_single(ndev->dev.parent, phys,
>  				 (cur_p->cntrl &
> XAXIDMA_BD_CTRL_LENGTH_MASK), @@ -645,8 +647,10 @@ static int
> axienet_free_tx_chain(struct net_device *ndev, u32 first_bd,
>  		cur_p->app1 = 0;
>  		cur_p->app2 = 0;
>  		cur_p->app4 = 0;
> -		cur_p->status = 0;
>  		cur_p->skb = NULL;
> +		/* ensure our transmit path and device don't prematurely see
> status cleared */
> +		wmb();
> +		cur_p->status = 0;

Any reason for moving status initialization down?

> 
>  		if (sizep)
>  			*sizep += status &
> XAXIDMA_BD_STS_ACTUAL_LEN_MASK; @@ -704,6 +708,9 @@ static inline
> int axienet_check_tx_bd_space(struct axienet_local *lp,
>  					    int num_frag)
>  {
>  	struct axidma_bd *cur_p;
> +
> +	/* Ensure we see all descriptor updates from device or TX IRQ path */
> +	rmb();
>  	cur_p = &lp->tx_bd_v[(lp->tx_bd_tail + num_frag) % lp->tx_bd_num];
>  	if (cur_p->status & XAXIDMA_BD_STS_ALL_MASK)
>  		return NETDEV_TX_BUSY;
> @@ -843,6 +850,8 @@ static void axienet_recv(struct net_device *ndev)
> 
>  		tail_p = lp->rx_bd_p + sizeof(*lp->rx_bd_v) * lp->rx_bd_ci;
> 
> +		/* Ensure we see complete descriptor update */
> +		dma_rmb();
>  		phys = desc_get_phys_addr(lp, cur_p);
>  		dma_unmap_single(ndev->dev.parent, phys, lp-
> >max_frm_size,
>  				 DMA_FROM_DEVICE);

Ideally we would also need a write barrier in xmit function just before 
updating tail descriptor.

> --
> 2.31.1




More information about the linux-arm-kernel mailing list