The branch main has been updated by wma:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=a6bda3e1ef4d06e3243a65533f9faf678816a48e

commit a6bda3e1ef4d06e3243a65533f9faf678816a48e
Author:     Kornel Duleba <min...@semihalf.com>
AuthorDate: 2022-01-27 09:24:26 +0000
Commit:     Wojciech Macek <w...@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

Reply via email to