[PATCH net V2 2/2] net: xilinx: axienet: Fix BQL accounting for multi-BD TX packets

Sean Anderson sean.anderson at linux.dev
Mon Mar 30 11:49:59 PDT 2026


On 3/27/26 03:32, Suraj Gupta wrote:
> When a TX packet spans multiple buffer descriptors (scatter-gather),
> axienet_free_tx_chain sums the per-BD actual length from descriptor
> status into a caller-provided accumulator. That sum is reset on each
> NAPI poll. If the BDs for a single packet complete across different
> polls, the earlier bytes are lost and never credited to BQL. This
> causes BQL to think bytes are permanently in-flight, eventually
> stalling the TX queue.
> 
> The SKB pointer is stored only on the last BD of a packet. When that
> BD completes, use skb->len for the byte count instead of summing
> per-BD status lengths. This matches netdev_sent_queue(), which debits
> skb->len, and naturally survives across polls because no partial
> packet contributes to the accumulator.
> 
> Fixes: c900e49d58eb ("net: xilinx: axienet: Implement BQL")
> Signed-off-by: Suraj Gupta <suraj.gupta2 at amd.com>
> ---
>  drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 9 ++++-----
>  1 file changed, 4 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> index b06e4c37ff61..263c4b67fd5a 100644
> --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
> @@ -770,8 +770,8 @@ static int axienet_device_reset(struct net_device *ndev)
>   * @first_bd:	Index of first descriptor to clean up
>   * @nr_bds:	Max number of descriptors to clean up
>   * @force:	Whether to clean descriptors even if not complete
> - * @sizep:	Pointer to a u32 filled with the total sum of all bytes
> - *		in all cleaned-up descriptors. Ignored if NULL.
> + * @sizep:	Pointer to a u32 accumulating the total byte count of
> + *		completed packets (using skb->len). Ignored if NULL.
>   * @budget:	NAPI budget (use 0 when not called from NAPI poll)
>   *
>   * Would either be called after a successful transmit operation, or after
> @@ -805,6 +805,8 @@ static int axienet_free_tx_chain(struct axienet_local *lp, u32 first_bd,
>  				 DMA_TO_DEVICE);
>  
>  		if (cur_p->skb && (status & XAXIDMA_BD_STS_COMPLETE_MASK)) {
> +			if (sizep)
> +				*sizep += cur_p->skb->len;
>  			napi_consume_skb(cur_p->skb, budget);
>  			packets++;
>  		}
> @@ -818,9 +820,6 @@ static int axienet_free_tx_chain(struct axienet_local *lp, u32 first_bd,
>  		wmb();
>  		cur_p->cntrl = 0;
>  		cur_p->status = 0;
> -
> -		if (sizep)
> -			*sizep += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK;
>  	}
>  
>  	if (!force) {

Reviewed-by: Sean Anderson <sean.anderson at linux.dev>

Although FWIW this may result in slightly-different statistics. Not sure
if we care since this will only affect packets that could not be sent
for whatever reason (collisions, loss of carrier, etc.)



More information about the linux-arm-kernel mailing list