mirror of
https://github.com/torvalds/linux.git
synced 2025-11-01 09:09:47 +02:00
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:
parent
295ce1eb36
commit
bd5afca115
1 changed files with 15 additions and 1 deletions
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue