mirror of
https://github.com/torvalds/linux.git
synced 2025-11-02 01:29:02 +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
|
#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,
|
static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
|
||||||
struct net_device *dev)
|
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);
|
txq = netdev_get_tx_queue(dev, qid);
|
||||||
nr_frags = 1 + skb_shinfo(skb)->nr_frags;
|
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 */
|
/* not enough space in the queue */
|
||||||
netif_tx_stop_queue(txq);
|
netif_tx_stop_queue(txq);
|
||||||
spin_unlock_bh(&q->lock);
|
spin_unlock_bh(&q->lock);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue