Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: xilinx: axienet: Fix packet counting

axienet_free_tx_chain returns the number of DMA descriptors it's
handled. However, axienet_tx_poll treats the return as the number of
packets. When scatter-gather SKBs are enabled, a single packet may use
multiple DMA descriptors, which causes incorrect packet counts. Fix this
by explicitly keepting track of the number of packets processed as
separate from the DMA descriptors.

Budget does not affect the number of Tx completions we can process for
NAPI, so we use the ring size as the limit instead of budget. As we no
longer return the number of descriptors processed to axienet_tx_poll, we
now update tx_bd_ci in axienet_free_tx_chain.

Fixes: 8a3b7a252dca ("drivers/net/ethernet/xilinx: added Xilinx AXI Ethernet driver")
Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
Link: https://patch.msgid.link/20240913145156.2283067-1-sean.anderson@linux.dev
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Sean Anderson and committed by
Paolo Abeni
5a6caa2c ba0da2dc

+14 -9
+14 -9
drivers/net/ethernet/xilinx/xilinx_axienet_main.c
··· 736 736 * 737 737 * Would either be called after a successful transmit operation, or after 738 738 * there was an error when setting up the chain. 739 - * Returns the number of descriptors handled. 739 + * Returns the number of packets handled. 740 740 */ 741 741 static int axienet_free_tx_chain(struct axienet_local *lp, u32 first_bd, 742 742 int nr_bds, bool force, u32 *sizep, int budget) 743 743 { 744 744 struct axidma_bd *cur_p; 745 745 unsigned int status; 746 + int i, packets = 0; 746 747 dma_addr_t phys; 747 - int i; 748 748 749 749 for (i = 0; i < nr_bds; i++) { 750 750 cur_p = &lp->tx_bd_v[(first_bd + i) % lp->tx_bd_num]; ··· 763 763 (cur_p->cntrl & XAXIDMA_BD_CTRL_LENGTH_MASK), 764 764 DMA_TO_DEVICE); 765 765 766 - if (cur_p->skb && (status & XAXIDMA_BD_STS_COMPLETE_MASK)) 766 + if (cur_p->skb && (status & XAXIDMA_BD_STS_COMPLETE_MASK)) { 767 767 napi_consume_skb(cur_p->skb, budget); 768 + packets++; 769 + } 768 770 769 771 cur_p->app0 = 0; 770 772 cur_p->app1 = 0; ··· 782 780 *sizep += status & XAXIDMA_BD_STS_ACTUAL_LEN_MASK; 783 781 } 784 782 785 - return i; 783 + if (!force) { 784 + lp->tx_bd_ci += i; 785 + if (lp->tx_bd_ci >= lp->tx_bd_num) 786 + lp->tx_bd_ci %= lp->tx_bd_num; 787 + } 788 + 789 + return packets; 786 790 } 787 791 788 792 /** ··· 961 953 u32 size = 0; 962 954 int packets; 963 955 964 - packets = axienet_free_tx_chain(lp, lp->tx_bd_ci, budget, false, &size, budget); 956 + packets = axienet_free_tx_chain(lp, lp->tx_bd_ci, lp->tx_bd_num, false, 957 + &size, budget); 965 958 966 959 if (packets) { 967 - lp->tx_bd_ci += packets; 968 - if (lp->tx_bd_ci >= lp->tx_bd_num) 969 - lp->tx_bd_ci %= lp->tx_bd_num; 970 - 971 960 u64_stats_update_begin(&lp->tx_stat_sync); 972 961 u64_stats_add(&lp->tx_packets, packets); 973 962 u64_stats_add(&lp->tx_bytes, size);