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: 23020f0493 ("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>
This commit is contained in:
Lorenzo Bianconi 2025-10-12 11:19:44 +02:00 committed by Paolo Abeni
parent 295ce1eb36
commit bd5afca115

View file

@ -1873,6 +1873,20 @@ static u32 airoha_get_dsa_tag(struct sk_buff *skb, struct net_device *dev)
#endif
}
static bool airoha_dev_tx_queue_busy(struct airoha_queue *q, u32 nr_frags)
{
u32 tail = q->tail <= q->head ? q->tail + q->ndesc : q->tail;
u32 index = q->head + nr_frags;
/* completion napi can free out-of-order tx descriptors if hw QoS is
* enabled and packets with different priorities are queued to the same
* DMA ring. Take into account possible out-of-order reports checking
* if the tx queue is full using circular buffer head/tail pointers
* instead of the number of queued packets.
*/
return index >= tail;
}
static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
struct net_device *dev)
{
@ -1926,7 +1940,7 @@ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
txq = netdev_get_tx_queue(dev, qid);
nr_frags = 1 + skb_shinfo(skb)->nr_frags;
if (q->queued + nr_frags > q->ndesc) {
if (airoha_dev_tx_queue_busy(q, nr_frags)) {
/* not enough space in the queue */
netif_tx_stop_queue(txq);
spin_unlock_bh(&q->lock);