git: 86a88972dc31 - main - DPAA: Minor performance improvements
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 21 Aug 2026 02:26:52 UTC
The branch main has been updated by jhibbits:
URL: https://cgit.FreeBSD.org/src/commit/?id=86a88972dc311b5d4fd112564bfe19c6d7549b5f
commit 86a88972dc311b5d4fd112564bfe19c6d7549b5f
Author: Justin Hibbits <jhibbits@FreeBSD.org>
AuthorDate: 2026-07-26 04:01:51 +0000
Commit: Justin Hibbits <jhibbits@FreeBSD.org>
CommitDate: 2026-08-21 02:26:10 +0000
DPAA: Minor performance improvements
* Add interrupt coalescing for DQRR and MR, with thresholds and period
as tunable sysctls under the `hw.qman` tree.
* Do lazy/sloppy buffer management to avoid constantly checking
thresholds via QMan portal round-trips.
* Add cache stashing to prewarm caches, reducing latency.
* Fix the definition of Context_A in the init_fq MC command/result
structures, they're 64-bit fields, not 32-bit.
* Reorder the dpaa_eth_frame_info as a bit of cleanup.
* Take advantage of the fact that UMA small allocations are returned in
the DMAP, and avoid pmap_kextract().
These changes together improve throughput by ~1.5%
(925Mbps->935-940Mbps) consistently, and reduce CPU usage by a bit,
increasing idle CPU from 30%->35% minimum.
---
sys/dev/dpaa/dpaa_eth.c | 139 +++++++++++++++++++++++++++++++-------------
sys/dev/dpaa/dpaa_eth.h | 9 ++-
sys/dev/dpaa/qman.c | 28 ++++++++-
sys/dev/dpaa/qman.h | 3 +-
sys/dev/dpaa/qman_portals.c | 88 ++++++++++++++++++++++++++++
sys/dev/dpaa/qman_var.h | 6 +-
6 files changed, 227 insertions(+), 46 deletions(-)
diff --git a/sys/dev/dpaa/dpaa_eth.c b/sys/dev/dpaa/dpaa_eth.c
index 6424a6e0b0c3..2fb902c4d300 100644
--- a/sys/dev/dpaa/dpaa_eth.c
+++ b/sys/dev/dpaa/dpaa_eth.c
@@ -73,16 +73,42 @@
#define DPAA_ETH_UNLOCK(sc) mtx_unlock(&(sc)->sc_lock)
#define DPAA_ETH_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_lock, MA_OWNED)
+/*
+ * On 64-bit Book-E the direct map is always present, and the driver's
+ * UMA zones plus page-sized mbuf clusters live in it. Bypass the
+ * page-table walk in pmap_kextract() for those; fall back for
+ * MJUM9BYTES/MJUM16BYTES clusters, which are kmem_alloc_contig()'d
+ * into KVA.
+ */
+static inline vm_paddr_t
+dpaa_eth_va_to_phys(vm_offset_t va)
+{
+ if (__predict_true(va >= DMAP_BASE_ADDRESS && va <= DMAP_MAX_ADDRESS))
+ return (DMAP_TO_PHYS(va));
+ return (pmap_kextract(va));
+}
+
/**
* @group dTSEC RM private defines.
* @{
*/
#define DTSEC_BPOOLS_USED (1)
#define DTSEC_MAX_TX_QUEUE_LEN 256
+/*
+ * Sample the hardware TX FQ counter every Nth packet. The FQ counter is
+ * 24 bits and the soft cap above is 256, so overshoot by N is trivial.
+ */
+#define DTSEC_MAX_TX_QUEUE_CHECK_INTERVAL 32
+/*
+ * Confirmation callback drain-detection. Fast path (TX not backpressured)
+ * skips the MC call entirely; when flagged, we sample every Nth callback to
+ * detect the drain-to-zero transition.
+ */
+#define DTSEC_TX_CONF_CHECK_INTERVAL 32
struct dpaa_eth_frame_info {
- struct mbuf *fi_mbuf;
struct fman_internal_context fi_ic;
+ struct mbuf *fi_mbuf;
struct dpaa_sgte fi_sgt[DPAA_NUM_OF_SG_TABLE_ENTRY];
};
@@ -90,6 +116,13 @@ enum dpaa_eth_pool_params {
DTSEC_RM_POOL_RX_LOW_MARK = 16,
DTSEC_RM_POOL_RX_HIGH_MARK = 64,
DTSEC_RM_POOL_RX_MAX_SIZE = 256,
+ /*
+ * MAX_SIZE is a soft cap set well below the BMan hardware pool
+ * limit, so sampling the depth every N put-backs per CPU is safe:
+ * worst-case overshoot is N * ncpus buffers, still tiny vs. the
+ * hardware pool.
+ */
+ DTSEC_RM_POOL_RX_CHECK_INTERVAL = 32,
DTSEC_RM_POOL_FI_LOW_MARK = 16,
DTSEC_RM_POOL_FI_HIGH_MARK = 64,
@@ -227,7 +260,7 @@ dtsec_add_buffers(struct dpaa_eth_softc *sc, int count)
b = uma_zalloc(sc->sc_rx_zone, M_NOWAIT);
if (b == NULL)
return (ENOMEM);
- pa = pmap_kextract((vm_offset_t)b);
+ pa = DMAP_TO_PHYS((vm_offset_t)b);
bufs[i].buf_hi = (pa >> 32);
bufs[i].buf_lo = (pa & 0xffffffff);
}
@@ -273,6 +306,9 @@ dpaa_eth_pool_rx_free(struct dpaa_eth_softc *sc)
if (sc->sc_rx_zone != NULL)
uma_zdestroy(sc->sc_rx_zone);
+
+ free(sc->sc_rx_pool_check_cnt, M_DEVBUF);
+ sc->sc_rx_pool_check_cnt = NULL;
}
int
@@ -288,6 +324,10 @@ dpaa_eth_pool_rx_init(struct dpaa_eth_softc *sc)
sc->sc_rx_zone = uma_zcreate(sc->sc_rx_zname, MCLBYTES, NULL,
NULL, NULL, NULL, MCLBYTES - 1, 0);
+ sc->sc_rx_pool_check_cnt = malloc_aligned(
+ (mp_maxid + 1) * sizeof(struct dpaa_pcpu_cnt),
+ CACHE_LINE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO);
+
sc->sc_rx_pool = bman_pool_create(&sc->sc_rx_bpid, MCLBYTES,
DTSEC_RM_POOL_RX_MAX_SIZE, DTSEC_RM_POOL_RX_LOW_MARK,
DTSEC_RM_POOL_RX_HIGH_MARK, 0, 0, dpaa_eth_pool_rx_depleted, sc);
@@ -316,11 +356,19 @@ dpaa_eth_fq_mext_free(struct mbuf *m)
buffer = m->m_ext.ext_arg1;
sc = m->m_ext.ext_arg2;
- if (bman_count(sc->sc_rx_pool) <= DTSEC_RM_POOL_RX_MAX_SIZE)
- bman_put_buffer(sc->sc_rx_pool,
- pmap_kextract((vm_offset_t)buffer), sc->sc_rx_bpid);
- else
+ /*
+ * Sloppy per-CPU sampling: no pin, no atomic. A stray migration
+ * between the curcpu read and the increment can only mis-attribute
+ * one bump to the wrong CPU's counter; the sampling rate stays
+ * within the acceptable slop window.
+ */
+ if ((++sc->sc_rx_pool_check_cnt[curcpu].cnt &
+ (DTSEC_RM_POOL_RX_CHECK_INTERVAL - 1)) == 0 &&
+ bman_count(sc->sc_rx_pool) > DTSEC_RM_POOL_RX_MAX_SIZE)
dpaa_eth_pool_rx_put_buffer(sc, buffer, NULL);
+ else
+ bman_put_buffer(sc->sc_rx_pool,
+ DMAP_TO_PHYS((vm_offset_t)buffer), sc->sc_rx_bpid);
}
static int
@@ -421,8 +469,6 @@ dpaa_eth_fq_tx_confirm_callback(device_t portal, struct qman_fq *fq,
{
struct dpaa_eth_frame_info *fi;
struct dpaa_eth_softc *sc;
- unsigned int qlen;
- struct dpaa_sgte *sgt0;
sc = app;
@@ -434,25 +480,33 @@ dpaa_eth_fq_tx_confirm_callback(device_t portal, struct qman_fq *fq,
* We are storing struct dpaa_eth_frame_info in first entry
* of scatter-gather table.
*/
- sgt0 = (struct dpaa_sgte *)PHYS_TO_DMAP(frame->addr + frame->offset);
- fi = (struct dpaa_eth_frame_info *)PHYS_TO_DMAP(sgt0->addr);
+ fi = (struct dpaa_eth_frame_info *)PHYS_TO_DMAP(frame->addr);
/* Free transmitted frame */
m_freem(fi->fi_mbuf);
dpaa_eth_fi_free(sc, fi);
- qlen = qman_fq_get_counter(sc->sc_tx_conf_fq, QMAN_COUNTER_FRAME);
-
- if (qlen == 0) {
- DPAA_ETH_LOCK(sc);
-
- if (sc->sc_tx_fq_full) {
- sc->sc_tx_fq_full = 0;
- dpaa_eth_if_start_locked(sc);
- }
-
- DPAA_ETH_UNLOCK(sc);
+ /*
+ * Fast path: TX isn't backpressured, so there's nothing to
+ * restart. Acquire load pairs with the release store on the
+ * TX path so a concurrent set of the flag is observed here.
+ */
+ if (atomic_load_acq_int(&sc->sc_tx_fq_full) == 0)
+ return (1);
+
+ /* Rate-limit the MC round-trip to detect drain-to-zero. */
+ if ((sc->sc_tx_conf_check_cnt++ &
+ (DTSEC_TX_CONF_CHECK_INTERVAL - 1)) != 0)
+ return (1);
+ if (qman_fq_get_counter(sc->sc_tx_conf_fq, QMAN_COUNTER_FRAME) != 0)
+ return (1);
+
+ DPAA_ETH_LOCK(sc);
+ if (sc->sc_tx_fq_full) {
+ atomic_store_rel_int(&sc->sc_tx_fq_full, 0);
+ dpaa_eth_if_start_locked(sc);
}
+ DPAA_ETH_UNLOCK(sc);
return (1);
}
@@ -484,8 +538,13 @@ dpaa_eth_fq_rx_init(struct dpaa_eth_softc *sc)
/* Default Frame Queue */
if (sc->sc_rx_channel == 0)
sc->sc_rx_channel = qman_alloc_channel();
+ /*
+ * Stash 1 cacheline of frame annotation (parse result / IC) and
+ * 1 of frame data head into the destination core's cache when
+ * QMan dequeues an RX frame -- the RX callback reads both.
+ */
fq = qman_fq_create(1, sc->sc_rx_channel, DTSEC_RM_FQR_RX_WQ,
- false, 0, false, false, true, false, 0, 0, 0);
+ false, 0, false, false, true, false, 0, 0, 0, 1, 1);
if (fq == NULL) {
device_printf(sc->sc_dev,
"could not create default RX queue\n");
@@ -529,7 +588,8 @@ dpaa_eth_fq_tx_init(struct dpaa_eth_softc *sc)
/* TX Frame Queue */
fq = qman_fq_create(1, sc->sc_port_tx_qman_chan,
- DTSEC_RM_FQR_TX_WQ, false, 0, false, false, true, false, 0, 0, 0);
+ DTSEC_RM_FQR_TX_WQ, false, 0, false, false, true, false, 0, 0, 0,
+ 0, 0);
if (fq == NULL) {
device_printf(sc->sc_dev, "could not create default TX queue"
"\n");
@@ -543,7 +603,7 @@ dpaa_eth_fq_tx_init(struct dpaa_eth_softc *sc)
/* TX Confirmation Frame Queue */
fq = qman_fq_create(1, sc->sc_rx_channel,
DTSEC_RM_FQR_TX_CONF_WQ, false, 0, false, false, true, false, 0, 0,
- 0);
+ 0, 0, 0);
if (fq == NULL) {
device_printf(sc->sc_dev, "could not create TX confirmation "
"queue\n");
@@ -612,7 +672,7 @@ dpaa_eth_if_start_locked(struct dpaa_eth_softc *sc)
{
vm_size_t dsize, psize, ssize;
struct dpaa_eth_frame_info *fi;
- unsigned int qlen, i;
+ unsigned int i;
struct mbuf *m0, *m;
vm_offset_t vaddr;
struct dpaa_fd fd;
@@ -626,12 +686,16 @@ dpaa_eth_if_start_locked(struct dpaa_eth_softc *sc)
if ((if_getdrvflags(sc->sc_ifnet) & IFF_DRV_RUNNING) != IFF_DRV_RUNNING)
return;
- while (!if_sendq_empty(sc->sc_ifnet)) {
- /* Check length of the TX queue */
- qlen = qman_fq_get_counter(sc->sc_tx_fq, QMAN_COUNTER_FRAME);
+ if (sc->sc_tx_fq_full)
+ return;
- if (qlen >= DTSEC_MAX_TX_QUEUE_LEN) {
- sc->sc_tx_fq_full = 1;
+ while (!if_sendq_empty(sc->sc_ifnet)) {
+ if ((sc->sc_tx_queue_check_cnt++ &
+ (DTSEC_MAX_TX_QUEUE_CHECK_INTERVAL - 1)) == 0 &&
+ qman_fq_get_counter(sc->sc_tx_fq, QMAN_COUNTER_FRAME) >=
+ DTSEC_MAX_TX_QUEUE_LEN) {
+ atomic_store_rel_int(&sc->sc_tx_fq_full, 1);
+ sc->sc_tx_queue_check_cnt = 0;
return;
}
@@ -650,17 +714,11 @@ dpaa_eth_if_start_locked(struct dpaa_eth_softc *sc)
psize = 0;
dsize = 0;
fi->fi_mbuf = m0;
+
while (m && i < DPAA_NUM_OF_SG_TABLE_ENTRY) {
if (m->m_len == 0)
continue;
- /*
- * First entry in scatter-gather table is used to keep
- * pointer to frame info structure.
- */
- fi->fi_sgt[i].addr = pmap_kextract((vm_offset_t)fi);
- i++;
-
dsize = m->m_len;
vaddr = (vm_offset_t)m->m_data;
while (dsize > 0 && i < DPAA_NUM_OF_SG_TABLE_ENTRY) {
@@ -668,7 +726,7 @@ dpaa_eth_if_start_locked(struct dpaa_eth_softc *sc)
if (m->m_len < ssize)
ssize = m->m_len;
- fi->fi_sgt[i].addr = pmap_kextract(vaddr);
+ fi->fi_sgt[i].addr = dpaa_eth_va_to_phys(vaddr);
fi->fi_sgt[i].length = ssize;
fi->fi_sgt[i].extension = 0;
@@ -697,15 +755,14 @@ dpaa_eth_if_start_locked(struct dpaa_eth_softc *sc)
fi->fi_sgt[i - 1].final = 1;
- fd.addr = pmap_kextract((vm_offset_t)&fi->fi_ic);
+ fd.addr = DMAP_TO_PHYS((vm_offset_t)fi);
fd.length = psize;
fd.format = DPAA_FD_FORMAT_SHORT_MBSF;
fd.liodn = 0;
fd.bpid = 0;
fd.eliodn = 0;
- fd.offset = offsetof(struct dpaa_eth_frame_info, fi_sgt) -
- offsetof(struct dpaa_eth_frame_info, fi_ic);
+ fd.offset = offsetof(struct dpaa_eth_frame_info, fi_sgt);
fd.cmd_stat = dpaa_eth_tx_add_csum(fi);
DPAA_ETH_UNLOCK(sc);
diff --git a/sys/dev/dpaa/dpaa_eth.h b/sys/dev/dpaa/dpaa_eth.h
index 7832b4dd7bff..cc46dc5485d6 100644
--- a/sys/dev/dpaa/dpaa_eth.h
+++ b/sys/dev/dpaa/dpaa_eth.h
@@ -27,6 +27,10 @@
#ifndef DPAA_ETH_H_
#define DPAA_ETH_H_
+struct dpaa_pcpu_cnt {
+ u_int cnt;
+} __aligned(CACHE_LINE_SIZE);
+
struct dpaa_eth_softc {
/* XXX MII bus requires that struct ifnet is first!!! */
if_t sc_ifnet;
@@ -42,6 +46,7 @@ struct dpaa_eth_softc {
uint8_t sc_rx_bpid;
uma_zone_t sc_rx_zone;
char sc_rx_zname[64];
+ struct dpaa_pcpu_cnt *sc_rx_pool_check_cnt; /* per-CPU */
/* RX Frame Queue */
struct qman_fq *sc_rx_fq;
@@ -49,9 +54,11 @@ struct dpaa_eth_softc {
/* TX Frame Queue */
struct qman_fq *sc_tx_fq;
- bool sc_tx_fq_full;
+ volatile u_int sc_tx_fq_full;
+ u_int sc_tx_queue_check_cnt;
struct qman_fq *sc_tx_conf_fq;
uint32_t sc_tx_conf_fqid;
+ u_int sc_tx_conf_check_cnt;
/* Methods */
int (*sc_port_rx_init)
diff --git a/sys/dev/dpaa/qman.c b/sys/dev/dpaa/qman.c
index 9143ebde5cb4..fe609711f413 100644
--- a/sys/dev/dpaa/qman.c
+++ b/sys/dev/dpaa/qman.c
@@ -149,6 +149,13 @@
#define QM_FQCTRL_HOLDACTIVE 0x0002
#define QM_FQCTRL_LIC 0x0001
+/*
+ * Context_A stashing config.
+ */
+#define QM_STASHING_EXCL_ANNOTATION 0x04
+#define QM_STASHING_EXCL_DATA 0x02
+#define QM_STASHING_EXCL_CONTEXT 0x01
+
#define QMAN_CHANNEL_POOL1_REV1 0x21
#define QMAN_CHANNEL_POOL1_REV3 0x401
@@ -496,7 +503,8 @@ qman_fq_create(uint32_t fqids_num, int channel, uint8_t wq,
bool force_fqid, uint32_t fqid_or_align, bool init_parked,
bool hold_active, bool prefer_in_cache, bool congst_avoid_ena,
void *congst_group, int8_t overhead_accounting_len,
- uint32_t tail_drop_threshold)
+ uint32_t tail_drop_threshold,
+ uint8_t annotation_cl, uint8_t data_cl)
{
union qman_mc_command cmd;
struct qman_softc *sc;
@@ -529,6 +537,24 @@ qman_fq_create(uint32_t fqids_num, int channel, uint8_t wq,
(hold_active ? QM_FQCTRL_HOLDACTIVE : 0) |
(congst_avoid_ena ? QM_FQCTRL_AVOIDBLOCK : 0);
+ /*
+ * Configure hardware cache stashing: on dequeue, QMan will push
+ * the requested number of cachelines of frame annotation and/or
+ * frame data into the destination core's cache, hiding memory
+ * latency for the RX callback.
+ */
+ if (annotation_cl != 0 || data_cl != 0) {
+ uint64_t excl, cl;
+
+ excl = (annotation_cl != 0 ? QM_STASHING_EXCL_ANNOTATION : 0) |
+ (data_cl != 0 ? QM_STASHING_EXCL_DATA : 0);
+ cl = ((annotation_cl & 3) << 4) | ((data_cl & 3) << 2);
+ /* excl in wire byte 0 (bits 63-56), cl in wire byte 1. */
+ cmd.init_fq.context_a = (excl << 56) | (cl << 48);
+ cmd.init_fq.fq_ctrl |= QM_FQCTRL_CTXASTASH;
+ cmd.init_fq.we_mask |= QCSP_INIT_FQ_WE_CONTEXT_A;
+ }
+
critical_enter();
/* Ensure we have got QMan port initialized */
diff --git a/sys/dev/dpaa/qman.h b/sys/dev/dpaa/qman.h
index 0e841dbc6ae6..d02e6d8bf94c 100644
--- a/sys/dev/dpaa/qman.h
+++ b/sys/dev/dpaa/qman.h
@@ -245,7 +245,8 @@ struct qman_fq *qman_fq_create(uint32_t fqids_num, int channel,
uint8_t wq, bool force_fqid, uint32_t fqid_or_align, bool init_parked,
bool hold_active, bool prefer_in_cache, bool congst_avoid_ena,
void *congst_group, int8_t overhead_accounting_len,
- uint32_t tail_drop_threshold);
+ uint32_t tail_drop_threshold,
+ uint8_t annotation_cl, uint8_t data_cl);
/**
* Free Frame Queue Range.
diff --git a/sys/dev/dpaa/qman_portals.c b/sys/dev/dpaa/qman_portals.c
index 3b64aca71cb7..e0a67410884e 100644
--- a/sys/dev/dpaa/qman_portals.c
+++ b/sys/dev/dpaa/qman_portals.c
@@ -16,6 +16,8 @@
#include <sys/proc.h>
#include <sys/pcpu.h>
#include <sys/sched.h>
+#include <sys/smp.h> /* For CPU_FOREACH() */
+#include <sys/sysctl.h>
#include <ddb/ddb.h>
#include <machine/bus.h>
@@ -115,6 +117,7 @@
#define QCSP_IER 0x0e04
#define QCSP_ISDR 0x0e08
#define QCSP_IIR 0xe0c
+#define QCSP_ITPR 0x0e14
#define QM_EQCR_VERB_CMD_ENQUEUE 0x01
#define QM_EQCR_VERB_BIT_INT 0x04
@@ -130,6 +133,85 @@ DPAA_RING(qman_eqcr, QMAN_EQCR_COUNT, QCSP_EQCR_PI_CENA, QCSP_EQCR_CI_CENA,
DPAA_RING(qman_dqrr, QMAN_DQRR_COUNT, QCSP_DQRR_PI_CENA, QCSP_DQRR_CI_CENA,
QCSP_DQRR_PI_CINH, QCSP_DQRR_CI_CINH);
+/*
+ * dqrr_ithresh: fire DQRR interrupt once N (of 16) dequeues queued (1-15)
+ * mr_ithresh: fire MR interrupt after N messages (1-7)
+ * iperiod: timer bound on interrupt latency, in units of 256 QMan
+ * clocks (~32 us on typical QorIQ platform clock at 100)
+ */
+static int qman_dqrr_ithresh = 12;
+static int qman_mr_ithresh = 4;
+static int qman_iperiod = 100;
+
+static void
+qman_portal_update_reg(bus_size_t reg, uint32_t val)
+{
+ struct qman_portal_softc *sc;
+ device_t portal;
+ int cpu;
+
+ CPU_FOREACH(cpu) {
+ portal = DPCPU_ID_GET(cpu, qman_affine_portal);
+ if (portal == NULL)
+ continue;
+ sc = device_get_softc(portal);
+ bus_write_4(sc->sc_base.sc_mres[1], reg, val);
+ }
+}
+
+static int
+qman_sysctl_reg(struct sysctl_oid *oidp, struct sysctl_req *req,
+ int *var, int min, int max, bus_size_t reg)
+{
+ int val, error;
+
+ val = *var;
+ error = sysctl_handle_int(oidp, &val, 0, req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+ if (val < min || val > max)
+ return (EINVAL);
+ *var = val;
+ qman_portal_update_reg(reg, val);
+ return (0);
+}
+
+static int
+qman_sysctl_dqrr_ithresh(SYSCTL_HANDLER_ARGS)
+{
+ return (qman_sysctl_reg(oidp, req,
+ &qman_dqrr_ithresh, 1, 15, QCSP_DQRR_ITR));
+}
+
+static int
+qman_sysctl_mr_ithresh(SYSCTL_HANDLER_ARGS)
+{
+ return (qman_sysctl_reg(oidp, req,
+ &qman_mr_ithresh, 1, 7, QCSP_MR_ITR));
+}
+
+static int
+qman_sysctl_iperiod(SYSCTL_HANDLER_ARGS)
+{
+ return (qman_sysctl_reg(oidp, req,
+ &qman_iperiod, 1, 65535, QCSP_ITPR));
+}
+
+SYSCTL_NODE(_hw, OID_AUTO, qman, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
+ "QMan portal tunables");
+SYSCTL_PROC(_hw_qman, OID_AUTO, dqrr_ithresh,
+ CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
+ NULL, 0, qman_sysctl_dqrr_ithresh, "I",
+ "DQRR interrupt threshold (dequeues queued before interrupt; 1-15)");
+SYSCTL_PROC(_hw_qman, OID_AUTO, mr_ithresh,
+ CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
+ NULL, 0, qman_sysctl_mr_ithresh, "I",
+ "Message Ring interrupt threshold (messages queued before interrupt; 1-7)");
+SYSCTL_PROC(_hw_qman, OID_AUTO, iperiod,
+ CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
+ NULL, 0, qman_sysctl_iperiod, "I",
+ "Interrupt time period (units of 256 QMan clocks)");
+
/*
* pmode: one of the CFG_EPM constants.
* stash_prio: 0 or CFG_EP
@@ -208,6 +290,12 @@ qman_portal_attach(device_t dev, int cpu)
}
sc->sc_affine_channel = cell;
DPCPU_ID_SET(cpu, qman_affine_portal, dev);
+
+ /* Interrupt coalescing. See tunables above. */
+ bus_write_4(sc->sc_base.sc_mres[1], QCSP_DQRR_ITR, qman_dqrr_ithresh);
+ bus_write_4(sc->sc_base.sc_mres[1], QCSP_MR_ITR, qman_mr_ithresh);
+ bus_write_4(sc->sc_base.sc_mres[1], QCSP_ITPR, qman_iperiod);
+
bus_write_4(sc->sc_base.sc_mres[1], QCSP_IER,
QM_PIRQ_EQCI | QM_PIRQ_EQRI | QM_PIRQ_MRI | QM_PIRQ_CSCI |
QM_PIRQ_DQRI);
diff --git a/sys/dev/dpaa/qman_var.h b/sys/dev/dpaa/qman_var.h
index 8ed36bbb6a35..6d13340ca365 100644
--- a/sys/dev/dpaa/qman_var.h
+++ b/sys/dev/dpaa/qman_var.h
@@ -44,7 +44,7 @@ union qman_mc_command {
uint16_t ics_cred;
uint16_t td_thresh_oac;
uint32_t context_b;
- uint32_t context_a;
+ uint64_t context_a;
uint8_t _rsvd1[32];
} init_fq;
struct {
@@ -92,7 +92,7 @@ union qman_mc_result {
uint16_t ics_cred;
uint16_t td_thresh;
uint32_t context_b;
- uint32_t context_a;
+ uint64_t context_a; /* 8 bytes on the wire */
uint16_t oac;
uint8_t _rsvd1[30];
} query_fq;
@@ -130,6 +130,8 @@ union qman_mc_result {
uint8_t _rsvd[61];
} alter_fqs;
};
+_Static_assert(sizeof(union qman_mc_command) == 64, "MC command mis-sized");
+_Static_assert(sizeof(union qman_mc_result) == 64, "MC result mis-sized");
struct qman_mc {
uint8_t polarity;