The branch main has been updated by jhibbits:

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

commit 7733521e2b4948d5e3374b65d1af15a1b8abbf5a
Author:     Justin Hibbits <[email protected]>
AuthorDate: 2026-08-10 13:03:46 +0000
Commit:     Justin Hibbits <[email protected]>
CommitDate: 2026-08-24 03:11:25 +0000

    dpaa/qman: per-CPU pool channel service + FQID range allocator
    
    Add plumbing for future FMan KeyGen-driven multi-queue RX.  Pure
    infrastructure; no behavioural change for existing single-FQ
    consumers.
    
    qman:
    * New qman_percpu_channel(cpu) to get the per-CPU channel, needed for
      receive-side scaling.
    * New qman_alloc_fqid_range(count, *basep) / qman_free_fqid_range()
      reserve a contiguous FQID range so a later KeyGen-distribution
      caller can compute FQID = base + (hash & mask) and create each FQ
      individually with force_fqid=true (each landing on its own
      per-CPU channel).
    
    qman_fq_create:
    * Honor the force_fqid / fqid_or_align parameters: when force_fqid is
      set, use the caller-supplied FQID and skip the internal vmem_alloc.
      The fqids_num != 1 restriction is lifted; qman_fq_list[] now records
      the handle at every FQID slot in the range so DQRR dispatch works for
      the whole range.
    * Add fqid_count and force_fqid to struct qman_fq so qman_fq_free()
      can retire every FQ in the range.
---
 sys/dev/dpaa/qman.c     | 96 ++++++++++++++++++++++++++++++++++++++++---------
 sys/dev/dpaa/qman.h     | 15 ++++++++
 sys/dev/dpaa/qman_var.h |  4 ++-
 3 files changed, 98 insertions(+), 17 deletions(-)

diff --git a/sys/dev/dpaa/qman.c b/sys/dev/dpaa/qman.c
index 2cebae163dab..f0964502413d 100644
--- a/sys/dev/dpaa/qman.c
+++ b/sys/dev/dpaa/qman.c
@@ -446,6 +446,43 @@ qman_free_channel(int channel)
        vmem_free(sc->sc_qpalloc, channel, 1);
 }
 
+int
+qman_percpu_channel(int cpu)
+{
+       device_t portal;
+       struct qman_portal_softc *sc;
+
+       portal = DPCPU_ID_GET(cpu, qman_affine_portal);
+       if (portal == NULL)
+               return (-1);
+
+       sc = device_get_softc(portal);
+
+       return (sc->sc_affine_channel);
+}
+
+int
+qman_alloc_fqid_range(uint32_t count, uint32_t *basep)
+{
+       struct qman_softc *sc = qman_sc;
+       vmem_addr_t base;
+       int error;
+
+       error = vmem_alloc(sc->sc_fqalloc, count, M_BESTFIT | M_NOWAIT, &base);
+       if (error != 0)
+               return (error);
+       *basep = base;
+       return (0);
+}
+
+void
+qman_free_fqid_range(uint32_t base, uint32_t count)
+{
+       struct qman_softc *sc = qman_sc;
+
+       vmem_free(sc->sc_fqalloc, base, count);
+}
+
 /**
  * @group QMan API functions implementation.
  * @{
@@ -478,14 +515,28 @@ qman_fq_create(uint32_t fqids_num, int channel, uint8_t 
wq,
 
        sc = qman_sc;
 
-       if (fqids_num != 1) {
-               device_printf(sc->sc_dev,
-                   "Only one fq allocation allowed currently\n");
-               return (NULL);
-       }
-
        bzero(&cmd, sizeof(cmd));
-       vmem_alloc(sc->sc_fqalloc, fqids_num, M_BESTFIT | M_WAITOK, &fqid_base);
+       if (force_fqid) {
+               /*
+                * Caller has already reserved the FQID (typically via
+                * qman_alloc_fqid_range() for a KeyGen distribution range)
+                * and passes the concrete FQID via fqid_or_align.  Do not
+                * touch the vmem allocator; just record the base for
+                * downstream book-keeping.
+                */
+               fqid_base = fqid_or_align;
+       } else {
+               int error;
+
+               error = vmem_alloc(sc->sc_fqalloc, fqids_num,
+                   M_BESTFIT | M_WAITOK, &fqid_base);
+               if (error != 0) {
+                       device_printf(sc->sc_dev,
+                           "qman_fq_create: no FQID range of %u\n",
+                           fqids_num);
+                       return (NULL);
+               }
+       }
        cmd.init_fq.fqid = fqid_base;
        cmd.init_fq.count = fqids_num - 1;
        cmd.init_fq.dest_chan = channel;
@@ -529,14 +580,18 @@ qman_fq_create(uint32_t fqids_num, int channel, uint8_t 
wq,
 
        critical_exit();
        if (res == NULL || rslt != QMAN_MC_RES_OK) {
-               vmem_free(sc->sc_fqalloc, fqid_base, fqids_num);
+               if (!force_fqid)
+                       vmem_free(sc->sc_fqalloc, fqid_base, fqids_num);
                goto err;
        }
 
        fqh = malloc(sizeof(*fqh), M_QMAN, M_WAITOK | M_ZERO);
        fqh->fqid = fqid_base;
+       fqh->fqid_count = fqids_num;
+       fqh->force_fqid = force_fqid;
 
-       qman_fq_list[fqid_base] = fqh;
+       for (uint32_t i = 0; i < fqids_num; i++)
+               qman_fq_list[fqid_base + i] = fqh;
 
        return (fqh);
 
@@ -546,7 +601,7 @@ err:
 }
 
 static int
-qman_fq_retire(device_t portal, struct qman_fq *fq)
+qman_fq_retire_one(device_t portal, uint32_t fqid)
 {
        union qman_mc_command cmd;
        union qman_mc_result *rr;
@@ -554,7 +609,7 @@ qman_fq_retire(device_t portal, struct qman_fq *fq)
        bzero(&cmd, sizeof(cmd));
 
        cmd.alter_fqs.verb = QCSP_VERB_ALTER_FQ_RETIRE;
-       cmd.alter_fqs.fqid = fq->fqid;
+       cmd.alter_fqs.fqid = fqid;
        rr = QMAN_PORTAL_MC_SEND_RAW(portal, &cmd);
        if (rr == NULL)
                return (ETIMEDOUT);
@@ -573,18 +628,27 @@ int
 qman_fq_free(struct qman_fq *fq)
 {
        struct qman_softc *sc;
+       device_t portal;
        int error;
 
        sc = qman_sc;
 
        critical_enter();
-       error = qman_fq_retire(DPCPU_GET(qman_affine_portal), fq);
+       portal = DPCPU_GET(qman_affine_portal);
+       for (uint32_t i = 0; i < fq->fqid_count; i++) {
+               error = qman_fq_retire_one(portal, fq->fqid + i);
+               if (error != 0) {
+                       critical_exit();
+                       return (error);
+               }
+       }
        /* TODO: Take FQ out of service. */
        critical_exit();
-       if (error != 0)
-               return (error);
-       vmem_free(sc->sc_fqalloc, fq->fqid, 1);
-       qman_fq_list[fq->fqid] = NULL;
+
+       if (!fq->force_fqid)
+               vmem_free(sc->sc_fqalloc, fq->fqid, fq->fqid_count);
+       for (uint32_t i = 0; i < fq->fqid_count; i++)
+               qman_fq_list[fq->fqid + i] = NULL;
        free(fq, M_QMAN);
 
        return (0);
diff --git a/sys/dev/dpaa/qman.h b/sys/dev/dpaa/qman.h
index d02e6d8bf94c..f09d57dc45c6 100644
--- a/sys/dev/dpaa/qman.h
+++ b/sys/dev/dpaa/qman.h
@@ -314,6 +314,21 @@ int qman_alloc_channel(void);
  */
 void qman_free_channel(int);
 
+/*
+ * Look up the pool channel for @cpu.  Each portal has a dedicated channel, and
+ * there is one portal per CPU.
+ */
+int qman_percpu_channel(int cpu);
+
+/*
+ * Reserve a contiguous range of @count FQIDs (needed by callers that
+ * program a KeyGen-style base+mask distribution and then create the
+ * individual FQs one-by-one with force_fqid=true).  Returns 0 on
+ * success and writes the base FQID to *basep.
+ */
+int qman_alloc_fqid_range(uint32_t count, uint32_t *basep);
+void qman_free_fqid_range(uint32_t base, uint32_t count);
+
 /**
  * Poll frames from QMan.
  * This polls frames from the current software portal.
diff --git a/sys/dev/dpaa/qman_var.h b/sys/dev/dpaa/qman_var.h
index 8e30314688c0..2d64c10d534c 100644
--- a/sys/dev/dpaa/qman_var.h
+++ b/sys/dev/dpaa/qman_var.h
@@ -178,7 +178,9 @@ struct qman_mc {
 };
 
 struct qman_fq {
-       uint32_t fqid;
+       uint32_t fqid;                  /* base FQID of the range */
+       uint32_t fqid_count;            /* length of the range (>=1) */
+       bool     force_fqid;            /* caller owns the FQID allocation */
        struct qman_cb cb;
 };
 

Reply via email to