git: a6bda3e1ef4d - main - enetc: Simply TX ring credits counting logic
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 31 Jan 2022 08:00:03 UTC
The branch main has been updated by wma: URL: https://cgit.FreeBSD.org/src/commit/?id=a6bda3e1ef4d06e3243a65533f9faf678816a48e commit a6bda3e1ef4d06e3243a65533f9faf678816a48e Author: Kornel Duleba <mindal@semihalf.com> AuthorDate: 2022-01-27 09:24:26 +0000 Commit: Wojciech Macek <wma@FreeBSD.org> CommitDate: 2022-01-31 07:57:48 +0000 enetc: Simply TX ring credits counting logic According to the RM rings can hold at most ring_size - 1 descriptors at any time. No additional logic is needed since iflib already respects this constrain. Thanks to that the pidx == cidx situation is not ambiguous and indicates an empty ring. Use that to simplify the logic that calculates the amount of processed frames. Obtained from: Semihalf Sponsored by: Alstom Group --- sys/dev/enetc/enetc.h | 3 +-- sys/dev/enetc/if_enetc.c | 36 ++++++++++++++++++++---------------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/sys/dev/enetc/enetc.h b/sys/dev/enetc/enetc.h index 57edc2b26f2c..84b109a3e144 100644 --- a/sys/dev/enetc/enetc.h +++ b/sys/dev/enetc/enetc.h @@ -52,8 +52,7 @@ struct enetc_tx_queue { union enetc_tx_bd *ring; uint64_t ring_paddr; - qidx_t next_to_clean; - bool ring_full; + qidx_t cidx; struct if_irq irq; }; diff --git a/sys/dev/enetc/if_enetc.c b/sys/dev/enetc/if_enetc.c index 6f15db3ffe6c..75c582e81696 100644 --- a/sys/dev/enetc/if_enetc.c +++ b/sys/dev/enetc/if_enetc.c @@ -503,8 +503,7 @@ enetc_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t *paddrs, queue->sc = sc; queue->ring = (union enetc_tx_bd*)(vaddrs[i]); queue->ring_paddr = paddrs[i]; - queue->next_to_clean = 0; - queue->ring_full = false; + queue->cidx = 0; } return (0); @@ -1125,8 +1124,6 @@ enetc_isc_txd_encap(void *data, if_pkt_info_t ipi) desc->flags |= ENETC_TXBD_FLAGS_F; ipi->ipi_new_pidx = pidx; - if (pidx == queue->next_to_clean) - queue->ring_full = true; return (0); } @@ -1144,28 +1141,35 @@ enetc_isc_txd_credits_update(void *data, uint16_t qid, bool clear) { struct enetc_softc *sc = data; struct enetc_tx_queue *queue; - qidx_t next_to_clean, next_to_process; - int clean_count; + int cidx, hw_cidx, count; queue = &sc->tx_queues[qid]; - next_to_process = - ENETC_TXQ_RD4(sc, qid, ENETC_TBCIR) & ENETC_TBCIR_IDX_MASK; - next_to_clean = queue->next_to_clean; + hw_cidx = ENETC_TXQ_RD4(sc, qid, ENETC_TBCIR) & ENETC_TBCIR_IDX_MASK; + cidx = queue->cidx; - if (next_to_clean == next_to_process && !queue->ring_full) + /* + * RM states that the ring can hold at most ring_size - 1 descriptors. + * Thanks to that we can assume that the ring is empty if cidx == pidx. + * This requirement is guaranteed implicitly by iflib as it will only + * encap a new frame if we have at least nfrags + 2 descriptors available + * on the ring. This driver uses at most one additional descriptor for + * VLAN tag insertion. + * Also RM states that the TBCIR register is only updated once all + * descriptors in the chain have been processed. + */ + if (cidx == hw_cidx) return (0); if (!clear) return (1); - clean_count = next_to_process - next_to_clean; - if (clean_count <= 0) - clean_count += sc->tx_queue_size; + count = hw_cidx - cidx; + if (count < 0) + count += sc->tx_queue_size; - queue->next_to_clean = next_to_process; - queue->ring_full = false; + queue->cidx = hw_cidx; - return (clean_count); + return (count); } static int