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