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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'net-airoha-fix-airoha_qdma_cleanup_tx_queue-processing'

Lorenzo Bianconi says:

====================
net: airoha: Fix airoha_qdma_cleanup_tx_queue() processing

Add missing bits in airoha_qdma_cleanup_tx_queue routine.
Fix airoha_qdma_cleanup_tx_queue processing errors intorduced in commit
'3f47e67dff1f7 ("net: airoha: Add the capability to consume out-of-order
DMA tx descriptors")'.

v3: https://lore.kernel.org/r/20260416-airoha_qdma_cleanup_tx_queue-fix-net-v3-0-2b69f5788580@kernel.org
v2: https://lore.kernel.org/r/20260414-airoha_qdma_cleanup_tx_queue-fix-net-v2-1-875de57cc022@kernel.org
v1: https://lore.kernel.org/r/20260410-airoha_qdma_cleanup_tx_queue-fix-net-v1-1-b7171c8f1e78@kernel.org
====================

Link: https://patch.msgid.link/20260417-airoha_qdma_cleanup_tx_queue-fix-net-v4-0-e04bcc2c9642@kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+34 -6
+34 -6
drivers/net/ethernet/airoha/airoha_eth.c
··· 978 978 dma_addr_t dma_addr; 979 979 980 980 spin_lock_init(&q->lock); 981 - q->ndesc = size; 982 981 q->qdma = qdma; 983 982 q->free_thr = 1 + MAX_SKB_FRAGS; 984 983 INIT_LIST_HEAD(&q->tx_list); 985 984 986 - q->entry = devm_kzalloc(eth->dev, q->ndesc * sizeof(*q->entry), 985 + q->entry = devm_kzalloc(eth->dev, size * sizeof(*q->entry), 987 986 GFP_KERNEL); 988 987 if (!q->entry) 989 988 return -ENOMEM; 990 989 991 - q->desc = dmam_alloc_coherent(eth->dev, q->ndesc * sizeof(*q->desc), 990 + q->desc = dmam_alloc_coherent(eth->dev, size * sizeof(*q->desc), 992 991 &dma_addr, GFP_KERNEL); 993 992 if (!q->desc) 994 993 return -ENOMEM; 995 994 996 - for (i = 0; i < q->ndesc; i++) { 995 + for (i = 0; i < size; i++) { 997 996 u32 val = FIELD_PREP(QDMA_DESC_DONE_MASK, 1); 998 997 999 998 list_add_tail(&q->entry[i].list, &q->tx_list); 1000 999 WRITE_ONCE(q->desc[i].ctrl, cpu_to_le32(val)); 1001 1000 } 1001 + q->ndesc = size; 1002 1002 1003 1003 /* xmit ring drop default setting */ 1004 1004 airoha_qdma_set(qdma, REG_TX_RING_BLOCKING(qid), ··· 1063 1063 1064 1064 static void airoha_qdma_cleanup_tx_queue(struct airoha_queue *q) 1065 1065 { 1066 - struct airoha_eth *eth = q->qdma->eth; 1067 - int i; 1066 + struct airoha_qdma *qdma = q->qdma; 1067 + struct airoha_eth *eth = qdma->eth; 1068 + int i, qid = q - &qdma->q_tx[0]; 1069 + u16 index = 0; 1068 1070 1069 1071 spin_lock_bh(&q->lock); 1070 1072 for (i = 0; i < q->ndesc; i++) { 1071 1073 struct airoha_queue_entry *e = &q->entry[i]; 1074 + struct airoha_qdma_desc *desc = &q->desc[i]; 1072 1075 1073 1076 if (!e->dma_addr) 1074 1077 continue; ··· 1082 1079 e->dma_addr = 0; 1083 1080 e->skb = NULL; 1084 1081 list_add_tail(&e->list, &q->tx_list); 1082 + 1083 + /* Reset DMA descriptor */ 1084 + WRITE_ONCE(desc->ctrl, 0); 1085 + WRITE_ONCE(desc->addr, 0); 1086 + WRITE_ONCE(desc->data, 0); 1087 + WRITE_ONCE(desc->msg0, 0); 1088 + WRITE_ONCE(desc->msg1, 0); 1089 + WRITE_ONCE(desc->msg2, 0); 1090 + 1085 1091 q->queued--; 1086 1092 } 1093 + 1094 + if (!list_empty(&q->tx_list)) { 1095 + struct airoha_queue_entry *e; 1096 + 1097 + e = list_first_entry(&q->tx_list, struct airoha_queue_entry, 1098 + list); 1099 + index = e - q->entry; 1100 + } 1101 + /* Set TX_DMA_IDX to TX_CPU_IDX to notify the hw the QDMA TX ring is 1102 + * empty. 1103 + */ 1104 + airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid), TX_RING_CPU_IDX_MASK, 1105 + FIELD_PREP(TX_RING_CPU_IDX_MASK, index)); 1106 + airoha_qdma_rmw(qdma, REG_TX_DMA_IDX(qid), TX_RING_DMA_IDX_MASK, 1107 + FIELD_PREP(TX_RING_DMA_IDX_MASK, index)); 1108 + 1087 1109 spin_unlock_bh(&q->lock); 1088 1110 } 1089 1111