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

net: airoha: Take into account out-of-order tx completions in airoha_dev_xmit()

Completion napi can free out-of-order tx descriptors if hw QoS is
enabled and packets with different priority are queued to same DMA ring.
Take into account possible out-of-order reports checking if the tx queue
is full using circular buffer head/tail pointer instead of the number of
queued packets.

Fixes: 23020f0493270 ("net: airoha: Introduce ethernet support for EN7581 SoC")
Suggested-by: Simon Horman <horms@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20251012-airoha-tx-busy-queue-v2-1-a600b08bab2d@kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Lorenzo Bianconi and committed by
Paolo Abeni
bd5afca1 295ce1eb

+15 -1
+15 -1
drivers/net/ethernet/airoha/airoha_eth.c
··· 1873 1873 #endif 1874 1874 } 1875 1875 1876 + static bool airoha_dev_tx_queue_busy(struct airoha_queue *q, u32 nr_frags) 1877 + { 1878 + u32 tail = q->tail <= q->head ? q->tail + q->ndesc : q->tail; 1879 + u32 index = q->head + nr_frags; 1880 + 1881 + /* completion napi can free out-of-order tx descriptors if hw QoS is 1882 + * enabled and packets with different priorities are queued to the same 1883 + * DMA ring. Take into account possible out-of-order reports checking 1884 + * if the tx queue is full using circular buffer head/tail pointers 1885 + * instead of the number of queued packets. 1886 + */ 1887 + return index >= tail; 1888 + } 1889 + 1876 1890 static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb, 1877 1891 struct net_device *dev) 1878 1892 { ··· 1940 1926 txq = netdev_get_tx_queue(dev, qid); 1941 1927 nr_frags = 1 + skb_shinfo(skb)->nr_frags; 1942 1928 1943 - if (q->queued + nr_frags > q->ndesc) { 1929 + if (airoha_dev_tx_queue_busy(q, nr_frags)) { 1944 1930 /* not enough space in the queue */ 1945 1931 netif_tx_stop_queue(txq); 1946 1932 spin_unlock_bh(&q->lock);