git: 7f79802bf931 - main - dpaa2: Make cleanup budget values sysctl(9) tunable

From: Dmitry Salychev <dsl_at_FreeBSD.org>
Date: Thu, 10 Sep 2026 12:17:16 UTC
The branch main has been updated by dsl:

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

commit 7f79802bf93140c42f8b03aa7a943dcb1c064796
Author:     Dmitry Salychev <dsl@FreeBSD.org>
AuthorDate: 2026-09-10 12:13:37 +0000
Commit:     Dmitry Salychev <dsl@FreeBSD.org>
CommitDate: 2026-09-10 12:13:37 +0000

    dpaa2: Make cleanup budget values sysctl(9) tunable
    
    Reviewed by:            dsl
    Approved by:            dsl
    Obtained from:          flo_purplekraken.com
    MFC after:              3 weeks
    Differential Revision:  https://reviews.freebsd.org/D59497
    Event:                  EuroBSDcon Devsummit 2026
---
 sys/dev/dpaa2/dpaa2_ni.c | 112 ++++++++++++++++++++++++++++++++++++++---------
 sys/dev/dpaa2/dpaa2_ni.h |   7 +++
 2 files changed, 99 insertions(+), 20 deletions(-)

diff --git a/sys/dev/dpaa2/dpaa2_ni.c b/sys/dev/dpaa2/dpaa2_ni.c
index a07ece428e60..4bb79933d1f4 100644
--- a/sys/dev/dpaa2/dpaa2_ni.c
+++ b/sys/dev/dpaa2/dpaa2_ni.c
@@ -129,13 +129,10 @@
 MALLOC_DEFINE(M_DPAA2_TXB, "dpaa2_txb", "DPAA2 DMA-mapped buffer (Tx)");
 
 /*
- * How many times channel cleanup routine will be repeated if the RX or TX
- * budget was depleted.
+ * Minimum and maximum valid values for the cleanup sysctls.
  */
-#define DPAA2_CLEAN_BUDGET	128 /* sysctl(9)? */
-/* TX/RX budget for the channel cleanup task */
-#define DPAA2_TX_BUDGET		256 /* sysctl(9)? */
-#define DPAA2_RX_BUDGET		512 /* sysctl(9)? */
+#define DPAA2_CLEAN_BUDGET_MIN 8
+#define DPAA2_CLEAN_BUDGET_MAX 2048
 
 #define DPNI_IRQ_INDEX		0 /* Index of the only DPNI IRQ. */
 #define DPNI_IRQ_LINK_CHANGED	1 /* Link state changed */
@@ -461,8 +458,8 @@ static void dpaa2_ni_media_status(if_t , struct ifmediareq *);
 static void dpaa2_ni_media_tick(void *);
 
 /* Tx/Rx routines. */
-static int dpaa2_ni_rx_cleanup(struct dpaa2_channel *);
-static int dpaa2_ni_tx_cleanup(struct dpaa2_channel *);
+static int dpaa2_ni_rx_cleanup(struct dpaa2_channel *, const int budget);
+static int dpaa2_ni_tx_cleanup(struct dpaa2_channel *, const int budget);
 static void dpaa2_ni_tx(struct dpaa2_ni_softc *, struct dpaa2_channel *,
     struct dpaa2_ni_tx_ring *, struct mbuf *);
 static void dpaa2_ni_cleanup_task(void *, int);
@@ -482,6 +479,11 @@ static int dpaa2_ni_collect_stats(SYSCTL_HANDLER_ARGS);
 static int dpaa2_ni_collect_buf_num(SYSCTL_HANDLER_ARGS);
 static int dpaa2_ni_collect_buf_free(SYSCTL_HANDLER_ARGS);
 static int dpaa2_ni_sysctl_link_state(SYSCTL_HANDLER_ARGS);
+static int dpaa2_ni_sysctl_handle_int(struct sysctl_req *req,
+    struct dpaa2_atomic *value);
+static int dpaa2_ni_sysctl_handle_clean_budget(SYSCTL_HANDLER_ARGS);
+static int dpaa2_ni_sysctl_handle_tx_budget(SYSCTL_HANDLER_ARGS);
+static int dpaa2_ni_sysctl_handle_rx_budget(SYSCTL_HANDLER_ARGS);
 
 static int
 dpaa2_ni_probe(device_t dev)
@@ -528,6 +530,9 @@ dpaa2_ni_attach(device_t dev)
 
 	DPAA2_ATOMIC_XCHG(&sc->buf_num, 0);
 	DPAA2_ATOMIC_XCHG(&sc->buf_free, 0);
+	DPAA2_ATOMIC_XCHG(&sc->clean_budget, 128);
+	DPAA2_ATOMIC_XCHG(&sc->tx_budget, 256);
+	DPAA2_ATOMIC_XCHG(&sc->rx_budget, 512);
 
 	sc->rxd_dmat = NULL;
 	sc->qos_dmat = NULL;
@@ -1814,6 +1819,23 @@ dpaa2_ni_setup_sysctls(struct dpaa2_ni_softc *sc)
 	    sc, 0, dpaa2_ni_sysctl_link_state,
 	    "A", "DPNI link state information");
 
+	/* Add configuration tunables */
+	parent = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev));
+	node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "config",
+	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "configuration tunables");
+	parent = SYSCTL_CHILDREN(node);
+
+	/* Add cleanup budget tunables. */
+	SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "clean_budget",
+	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, 0,
+	    dpaa2_ni_sysctl_handle_clean_budget, "d", "clean budget");
+	SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "tx_budget",
+	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, 0,
+	    dpaa2_ni_sysctl_handle_tx_budget, "d", "tx budget");
+	SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "rx_budget",
+	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, 0,
+	    dpaa2_ni_sysctl_handle_rx_budget, "d", "rx budget");
+
 	return (0);
 }
 
@@ -2878,18 +2900,21 @@ dpaa2_ni_cleanup_task(void *arg, int count)
 {
 	struct dpaa2_channel *ch = (struct dpaa2_channel *)arg;
 	struct dpaa2_ni_softc *sc = device_get_softc(ch->ni_dev);
+	const int clean_budget = DPAA2_ATOMIC_READ(&sc->clean_budget);
+	const int tx_budget = DPAA2_ATOMIC_READ(&sc->tx_budget);
+	const int rx_budget = DPAA2_ATOMIC_READ(&sc->rx_budget);
 	int error, rxc, txc;
 
-	for (int i = 0; i < DPAA2_CLEAN_BUDGET; i++) {
-		rxc  = dpaa2_ni_rx_cleanup(ch);
-		txc  = dpaa2_ni_tx_cleanup(ch);
+	for (int i = 0; i < clean_budget; i++) {
+		rxc = dpaa2_ni_rx_cleanup(ch, rx_budget);
+		txc = dpaa2_ni_tx_cleanup(ch, tx_budget);
 
 		if (__predict_false((if_getdrvflags(sc->ifp) &
 		    IFF_DRV_RUNNING) == 0)) {
 			return;
 		}
 
-		if ((txc != DPAA2_TX_BUDGET) && (rxc != DPAA2_RX_BUDGET)) {
+		if ((txc != tx_budget) && (rxc != rx_budget)) {
 			break;
 		}
 	}
@@ -2906,13 +2931,13 @@ dpaa2_ni_cleanup_task(void *arg, int count)
  * @brief Poll frames from a specific channel when CDAN is received.
  */
 static int
-dpaa2_ni_rx_cleanup(struct dpaa2_channel *ch)
+dpaa2_ni_rx_cleanup(struct dpaa2_channel *ch, const int budget)
 {
 	struct dpaa2_io_softc *iosc = device_get_softc(ch->io_dev);
 	struct dpaa2_swp *swp = iosc->swp;
 	struct dpaa2_ni_fq *fq;
 	struct dpaa2_buf *buf = &ch->store;
-	int budget = DPAA2_RX_BUDGET;
+	int budget_remaining = budget;
 	int error, consumed = 0;
 
 	do {
@@ -2930,18 +2955,18 @@ dpaa2_ni_rx_cleanup(struct dpaa2_channel *ch)
 			device_printf(ch->ni_dev, "%s: timeout to consume "
 			    "frames: chan_id=%d\n", __func__, ch->id);
 		}
-	} while (--budget);
+	} while (--budget_remaining );
 
-	return (DPAA2_RX_BUDGET - budget);
+	return (budget - budget_remaining);
 }
 
 static int
-dpaa2_ni_tx_cleanup(struct dpaa2_channel *ch)
+dpaa2_ni_tx_cleanup(struct dpaa2_channel *ch, const int budget)
 {
 	struct dpaa2_ni_softc *sc = device_get_softc(ch->ni_dev);
 	struct dpaa2_ni_tx_ring *tx = &ch->txc_queue.tx_rings[0];
 	struct mbuf *m = NULL;
-	int budget = DPAA2_TX_BUDGET;
+	int budget_remaining = budget;
 
 	do {
 		mtx_assert(&ch->xmit_mtx, MA_NOTOWNED);
@@ -2955,9 +2980,9 @@ dpaa2_ni_tx_cleanup(struct dpaa2_channel *ch)
 		} else {
 			dpaa2_ni_tx(sc, ch, tx, m);
 		}
-	} while (--budget);
+	} while (--budget_remaining);
 
-	return (DPAA2_TX_BUDGET - budget);
+	return (budget - budget_remaining);
 }
 
 static void
@@ -3589,6 +3614,53 @@ dpaa2_ni_collect_buf_free(SYSCTL_HANDLER_ARGS)
 	return (sysctl_handle_32(oidp, &buf_free, 0, req));
 }
 
+/*
+ * Common sysctl handler function for integer values stored as dpaa2_atomic.
+ * Reads the current value from the atomic object and writes the new one to it.
+ */
+static inline int
+dpaa2_ni_sysctl_handle_int(struct sysctl_req *req, struct dpaa2_atomic *value)
+{
+	int error, tmp;
+
+	tmp = DPAA2_ATOMIC_READ(value);
+	error = SYSCTL_OUT(req, &tmp, sizeof(tmp));
+	if (error || req->newptr == NULL)
+		return error;
+	error = SYSCTL_IN(req, &tmp, sizeof(tmp));
+	if (error)
+		return error;
+	if ((tmp < DPAA2_CLEAN_BUDGET_MIN) || (tmp > DPAA2_CLEAN_BUDGET_MAX))
+		return EINVAL;
+	DPAA2_ATOMIC_XCHG(value, tmp);
+
+	return 0;
+}
+
+static int
+dpaa2_ni_sysctl_handle_clean_budget(SYSCTL_HANDLER_ARGS)
+{
+	struct dpaa2_ni_softc *sc = (struct dpaa2_ni_softc *)arg1;
+
+	return dpaa2_ni_sysctl_handle_int(req, &sc->clean_budget);
+}
+
+static int
+dpaa2_ni_sysctl_handle_tx_budget(SYSCTL_HANDLER_ARGS)
+{
+	struct dpaa2_ni_softc *sc = (struct dpaa2_ni_softc *)arg1;
+
+	return dpaa2_ni_sysctl_handle_int(req, &sc->tx_budget);
+}
+
+static int
+dpaa2_ni_sysctl_handle_rx_budget(SYSCTL_HANDLER_ARGS)
+{
+	struct dpaa2_ni_softc *sc = (struct dpaa2_ni_softc *)arg1;
+
+	return dpaa2_ni_sysctl_handle_int(req, &sc->rx_budget);
+}
+
 static int
 dpaa2_ni_set_hash(device_t dev, uint64_t flags)
 {
diff --git a/sys/dev/dpaa2/dpaa2_ni.h b/sys/dev/dpaa2/dpaa2_ni.h
index 51da539dfa66..7ae94783db3b 100644
--- a/sys/dev/dpaa2/dpaa2_ni.h
+++ b/sys/dev/dpaa2/dpaa2_ni.h
@@ -494,6 +494,13 @@ struct dpaa2_ni_softc {
 	/* sysctl(9) */
 	struct dpaa2_atomic	 buf_num;
 	struct dpaa2_atomic	 buf_free;
+	/*
+	 * How many times channel cleanup routine will be repeated if the RX or
+	 * TX budget was depleted.
+	 */
+	struct dpaa2_atomic	 clean_budget;
+	struct dpaa2_atomic	 tx_budget;
+	struct dpaa2_atomic	 rx_budget;
 
 	int			 irq_rid[DPAA2_NI_MSI_COUNT];
 	struct resource		*irq_res;