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 'simplify-tx-napi-logic-in-airoha_eth-driver'

Lorenzo Bianconi says:

====================
Simplify Tx napi logic in airoha_eth driver

Simplify Tx napi logic relying on the packet index provided by
completion queue indicating the completed packet that can be removed
from the Tx DMA ring.
Read completion queue head and pending entry in airoha_qdma_tx_napi_poll().
====================

Link: https://patch.msgid.link/20241029-airoha-en7581-tx-napi-work-v1-0-96ad1686b946@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+55 -51
+55 -51
drivers/net/ethernet/mediatek/airoha_eth.c
··· 752 752 struct airoha_qdma *qdma; 753 753 754 754 struct napi_struct napi; 755 - u32 *q; 756 755 757 756 int size; 758 - int queued; 759 - u16 head; 757 + u32 *q; 760 758 }; 761 759 762 760 struct airoha_hw_stats { ··· 1654 1656 static int airoha_qdma_tx_napi_poll(struct napi_struct *napi, int budget) 1655 1657 { 1656 1658 struct airoha_tx_irq_queue *irq_q; 1659 + int id, done = 0, irq_queued; 1657 1660 struct airoha_qdma *qdma; 1658 1661 struct airoha_eth *eth; 1659 - int id, done = 0; 1662 + u32 status, head; 1660 1663 1661 1664 irq_q = container_of(napi, struct airoha_tx_irq_queue, napi); 1662 1665 qdma = irq_q->qdma; 1663 1666 id = irq_q - &qdma->q_tx_irq[0]; 1664 1667 eth = qdma->eth; 1665 1668 1666 - while (irq_q->queued > 0 && done < budget) { 1667 - u32 qid, last, val = irq_q->q[irq_q->head]; 1669 + status = airoha_qdma_rr(qdma, REG_IRQ_STATUS(id)); 1670 + head = FIELD_GET(IRQ_HEAD_IDX_MASK, status); 1671 + head = head % irq_q->size; 1672 + irq_queued = FIELD_GET(IRQ_ENTRY_LEN_MASK, status); 1673 + 1674 + while (irq_queued > 0 && done < budget) { 1675 + u32 qid, val = irq_q->q[head]; 1676 + struct airoha_qdma_desc *desc; 1677 + struct airoha_queue_entry *e; 1668 1678 struct airoha_queue *q; 1679 + u32 index, desc_ctrl; 1680 + struct sk_buff *skb; 1669 1681 1670 1682 if (val == 0xff) 1671 1683 break; 1672 1684 1673 - irq_q->q[irq_q->head] = 0xff; /* mark as done */ 1674 - irq_q->head = (irq_q->head + 1) % irq_q->size; 1675 - irq_q->queued--; 1685 + irq_q->q[head] = 0xff; /* mark as done */ 1686 + head = (head + 1) % irq_q->size; 1687 + irq_queued--; 1676 1688 done++; 1677 1689 1678 - last = FIELD_GET(IRQ_DESC_IDX_MASK, val); 1679 1690 qid = FIELD_GET(IRQ_RING_IDX_MASK, val); 1680 - 1681 1691 if (qid >= ARRAY_SIZE(qdma->q_tx)) 1682 1692 continue; 1683 1693 ··· 1693 1687 if (!q->ndesc) 1694 1688 continue; 1695 1689 1690 + index = FIELD_GET(IRQ_DESC_IDX_MASK, val); 1691 + if (index >= q->ndesc) 1692 + continue; 1693 + 1696 1694 spin_lock_bh(&q->lock); 1697 1695 1698 - while (q->queued > 0) { 1699 - struct airoha_qdma_desc *desc = &q->desc[q->tail]; 1700 - struct airoha_queue_entry *e = &q->entry[q->tail]; 1701 - u32 desc_ctrl = le32_to_cpu(desc->ctrl); 1702 - struct sk_buff *skb = e->skb; 1703 - u16 index = q->tail; 1696 + if (!q->queued) 1697 + goto unlock; 1704 1698 1705 - if (!(desc_ctrl & QDMA_DESC_DONE_MASK) && 1706 - !(desc_ctrl & QDMA_DESC_DROP_MASK)) 1707 - break; 1699 + desc = &q->desc[index]; 1700 + desc_ctrl = le32_to_cpu(desc->ctrl); 1708 1701 1702 + if (!(desc_ctrl & QDMA_DESC_DONE_MASK) && 1703 + !(desc_ctrl & QDMA_DESC_DROP_MASK)) 1704 + goto unlock; 1705 + 1706 + e = &q->entry[index]; 1707 + skb = e->skb; 1708 + 1709 + dma_unmap_single(eth->dev, e->dma_addr, e->dma_len, 1710 + DMA_TO_DEVICE); 1711 + memset(e, 0, sizeof(*e)); 1712 + WRITE_ONCE(desc->msg0, 0); 1713 + WRITE_ONCE(desc->msg1, 0); 1714 + q->queued--; 1715 + 1716 + /* completion ring can report out-of-order indexes if hw QoS 1717 + * is enabled and packets with different priority are queued 1718 + * to same DMA ring. Take into account possible out-of-order 1719 + * reports incrementing DMA ring tail pointer 1720 + */ 1721 + while (q->tail != q->head && !q->entry[q->tail].dma_addr) 1709 1722 q->tail = (q->tail + 1) % q->ndesc; 1710 - q->queued--; 1711 1723 1712 - dma_unmap_single(eth->dev, e->dma_addr, e->dma_len, 1713 - DMA_TO_DEVICE); 1724 + if (skb) { 1725 + u16 queue = skb_get_queue_mapping(skb); 1726 + struct netdev_queue *txq; 1714 1727 1715 - WRITE_ONCE(desc->msg0, 0); 1716 - WRITE_ONCE(desc->msg1, 0); 1728 + txq = netdev_get_tx_queue(skb->dev, queue); 1729 + netdev_tx_completed_queue(txq, 1, skb->len); 1730 + if (netif_tx_queue_stopped(txq) && 1731 + q->ndesc - q->queued >= q->free_thr) 1732 + netif_tx_wake_queue(txq); 1717 1733 1718 - if (skb) { 1719 - u16 queue = skb_get_queue_mapping(skb); 1720 - struct netdev_queue *txq; 1721 - 1722 - txq = netdev_get_tx_queue(skb->dev, queue); 1723 - netdev_tx_completed_queue(txq, 1, skb->len); 1724 - if (netif_tx_queue_stopped(txq) && 1725 - q->ndesc - q->queued >= q->free_thr) 1726 - netif_tx_wake_queue(txq); 1727 - 1728 - dev_kfree_skb_any(skb); 1729 - e->skb = NULL; 1730 - } 1731 - 1732 - if (index == last) 1733 - break; 1734 + dev_kfree_skb_any(skb); 1734 1735 } 1735 - 1736 + unlock: 1736 1737 spin_unlock_bh(&q->lock); 1737 1738 } 1738 1739 ··· 2039 2026 2040 2027 if (intr[0] & INT_TX_MASK) { 2041 2028 for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) { 2042 - struct airoha_tx_irq_queue *irq_q = &qdma->q_tx_irq[i]; 2043 - u32 status, head; 2044 - 2045 2029 if (!(intr[0] & TX_DONE_INT_MASK(i))) 2046 2030 continue; 2047 2031 2048 2032 airoha_qdma_irq_disable(qdma, QDMA_INT_REG_IDX0, 2049 2033 TX_DONE_INT_MASK(i)); 2050 - 2051 - status = airoha_qdma_rr(qdma, REG_IRQ_STATUS(i)); 2052 - head = FIELD_GET(IRQ_HEAD_IDX_MASK, status); 2053 - irq_q->head = head % irq_q->size; 2054 - irq_q->queued = FIELD_GET(IRQ_ENTRY_LEN_MASK, status); 2055 - 2056 2034 napi_schedule(&qdma->q_tx_irq[i].napi); 2057 2035 } 2058 2036 }