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; };
