]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net: airoha: Add missing bits in airoha_qdma_cleanup_tx_queue()
authorLorenzo Bianconi <lorenzo@kernel.org>
Fri, 17 Apr 2026 06:36:32 +0000 (08:36 +0200)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 23 Apr 2026 07:07:57 +0000 (09:07 +0200)
Similar to airoha_qdma_cleanup_rx_queue(), reset DMA TX descriptors in
airoha_qdma_cleanup_tx_queue routine. Moreover, reset TX_DMA_IDX to
TX_CPU_IDX to notify the NIC the QDMA TX ring is empty.

Fixes: 23020f0493270 ("net: airoha: Introduce ethernet support for EN7581 SoC")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20260417-airoha_qdma_cleanup_tx_queue-fix-net-v4-2-e04bcc2c9642@kernel.org
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/airoha/airoha_eth.c

index 11c8d3589c45c5f9084dba18eea7fc0053a95f00..e17e40a2090d724f75a6b21a23707610fe131b14 100644 (file)
@@ -1063,12 +1063,15 @@ static int airoha_qdma_init_tx(struct airoha_qdma *qdma)
 
 static void airoha_qdma_cleanup_tx_queue(struct airoha_queue *q)
 {
-       struct airoha_eth *eth = q->qdma->eth;
-       int i;
+       struct airoha_qdma *qdma = q->qdma;
+       struct airoha_eth *eth = qdma->eth;
+       int i, qid = q - &qdma->q_tx[0];
+       u16 index = 0;
 
        spin_lock_bh(&q->lock);
        for (i = 0; i < q->ndesc; i++) {
                struct airoha_queue_entry *e = &q->entry[i];
+               struct airoha_qdma_desc *desc = &q->desc[i];
 
                if (!e->dma_addr)
                        continue;
@@ -1079,8 +1082,33 @@ static void airoha_qdma_cleanup_tx_queue(struct airoha_queue *q)
                e->dma_addr = 0;
                e->skb = NULL;
                list_add_tail(&e->list, &q->tx_list);
+
+               /* Reset DMA descriptor */
+               WRITE_ONCE(desc->ctrl, 0);
+               WRITE_ONCE(desc->addr, 0);
+               WRITE_ONCE(desc->data, 0);
+               WRITE_ONCE(desc->msg0, 0);
+               WRITE_ONCE(desc->msg1, 0);
+               WRITE_ONCE(desc->msg2, 0);
+
                q->queued--;
        }
+
+       if (!list_empty(&q->tx_list)) {
+               struct airoha_queue_entry *e;
+
+               e = list_first_entry(&q->tx_list, struct airoha_queue_entry,
+                                    list);
+               index = e - q->entry;
+       }
+       /* Set TX_DMA_IDX to TX_CPU_IDX to notify the hw the QDMA TX ring is
+        * empty.
+        */
+       airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid), TX_RING_CPU_IDX_MASK,
+                       FIELD_PREP(TX_RING_CPU_IDX_MASK, index));
+       airoha_qdma_rmw(qdma, REG_TX_DMA_IDX(qid), TX_RING_DMA_IDX_MASK,
+                       FIELD_PREP(TX_RING_DMA_IDX_MASK, index));
+
        spin_unlock_bh(&q->lock);
 }