Date: Sun, 03 May 2026 19:11:57 +0000 From: Justin Hibbits <jhibbits@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: fd8d34ce272b - main - dpaa: Migrate from NCSW base to a home-grown driver Message-ID: <69f79dfd.3d681.162b0f5@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by jhibbits: URL: https://cgit.FreeBSD.org/src/commit/?id=fd8d34ce272ba40f3e0218198ba542a29c390a4a commit fd8d34ce272ba40f3e0218198ba542a29c390a4a Author: Justin Hibbits <jhibbits@FreeBSD.org> AuthorDate: 2026-04-24 03:38:19 +0000 Commit: Justin Hibbits <jhibbits@FreeBSD.org> CommitDate: 2026-05-03 19:09:29 +0000 dpaa: Migrate from NCSW base to a home-grown driver The NCSW reference base requires tuning for each target, and currently is configured for FMANv2. This doesn't readily work on FMANv3 devices, such as the T-series powerpc, or the LS1043 ARM. Since Freescale/NXP abandoned the NCSW driver a decade ago, it makes sense to abandon it ourselves as well. This new driver uses a combination of the NCSW driver and the Linux driver (BSD/GPL dual licensed) as a reference, but contains no actual code from them. The DPAA (Data Path Acceleration Architecture) subsystem consists of the following components: * BMan -- Buffer Manager. Manages buffer pools of different sizes (one size per pool, up to 64 pools) * QMan -- Queue Manager. Manages the interfaces between DPAA-based components and the CPU(s). * FMan -- Frame Manager. Responsible for all ethernet-related processing. Consists itself of the following components: * Ports -- interfaces to the QMan. An ethernet interface consists of 2 ports. Ports use "Next-invoked action" (NIA) descriptors to form a pipeline for processing on receive and transmit. * Parser -- performs protocol header parsing and validation. Both hardware and software parsers are available. * KeyGen -- Key generator, used to start the classification process (for the Policer), generating FQIDs and other keys based on the frame input. * Policer -- performs traffic shaping and classification * MAC -- SoC specific ethernet MAC (dTSEC, TGEC, mEMAC). Currently supports dTSEC and mEMAC, along with their MDIO blocks. Additional components not yet handled: SEC -- Security engine (crypto) RE -- RAID engine RapidIO DCE -- Decompression/Compression engine, supports ZLIB, DEFLATE, and GZIP, as well as base64 encoding and decoding. BMan and QMan are accessed via cache-coherent portals, using ring buffers as I/O. The intent is for portals to be per-CPU (core/thread) to reduce locking contention and improve performance. This driver pins interrupt handlers to the CPU "owning" a given portal, and uses critical sections to prevent switching while accessing the portal. --- sys/conf/files.powerpc | 21 + sys/dev/dpaa/bman.c | 439 +++++++-------- sys/dev/dpaa/bman.h | 172 ++---- sys/dev/dpaa/bman_fdt.c | 154 +----- sys/dev/dpaa/bman_portals.c | 378 +++++++++---- sys/dev/dpaa/bman_var.h | 44 ++ sys/dev/dpaa/dpaa_common.c | 82 +++ sys/dev/dpaa/dpaa_common.h | 165 ++++++ sys/dev/dpaa/dpaa_eth.c | 634 +++++++++++++++++++++ sys/dev/dpaa/dpaa_eth.h | 116 ++++ sys/dev/dpaa/fman.c | 858 +++++++++++++++++++++-------- sys/dev/dpaa/fman.h | 73 ++- sys/dev/dpaa/fman_fdt.c | 14 +- sys/dev/dpaa/fman_if.m | 38 ++ sys/dev/dpaa/fman_mdio.c | 16 +- sys/dev/dpaa/fman_muram.c | 70 +++ sys/dev/dpaa/fman_port.c | 680 +++++++++++++++++++++++ sys/dev/dpaa/fman_port.h | 29 + sys/dev/dpaa/fman_port_if.m | 55 ++ sys/dev/dpaa/fman_xmdio.c | 284 ++++++++++ sys/dev/dpaa/if_dtsec.c | 614 +++++++-------------- sys/dev/dpaa/if_dtsec.h | 96 +--- sys/dev/dpaa/if_dtsec_fdt.c | 55 +- sys/dev/dpaa/if_dtsec_im.c | 260 --------- sys/dev/dpaa/if_dtsec_im.h | 39 -- sys/dev/dpaa/if_dtsec_rm.c | 651 ---------------------- sys/dev/dpaa/if_memac.c | 802 +++++++++++++++++++++++++++ sys/dev/dpaa/{if_dtsec_rm.h => if_memac.h} | 50 +- sys/dev/dpaa/if_memac_fdt.c | 190 +++++++ sys/dev/dpaa/portals.h | 51 +- sys/dev/dpaa/portals_common.c | 135 +---- sys/dev/dpaa/qman.c | 794 +++++++++++++++----------- sys/dev/dpaa/qman.h | 184 +++++-- sys/dev/dpaa/qman_fdt.c | 176 ++---- sys/dev/dpaa/qman_portal_if.m | 37 ++ sys/dev/dpaa/qman_portals.c | 490 ++++++++++++---- sys/dev/dpaa/qman_var.h | 167 ++++++ sys/powerpc/conf/QORIQ64 | 4 +- sys/powerpc/conf/dpaa/DPAA | 99 ---- sys/powerpc/conf/dpaa/config.dpaa | 24 - sys/powerpc/conf/dpaa/files.dpaa | 122 ---- 41 files changed, 6006 insertions(+), 3356 deletions(-) diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc index 164a5d01d4b9..a754f78b35f2 100644 --- a/sys/conf/files.powerpc +++ b/sys/conf/files.powerpc @@ -89,6 +89,27 @@ dev/adb/adb_hb_if.m optional adb dev/adb/adb_if.m optional adb dev/adb/adb_buttons.c optional adb dev/agp/agp_apple.c optional agp powermac +dev/dpaa/bman_portals.c optional dpaa fdt +dev/dpaa/bman.c optional dpaa +dev/dpaa/bman_fdt.c optional dpaa fdt +dev/dpaa/dpaa_eth.c optional dpaa +dev/dpaa/fman.c optional dpaa fdt +dev/dpaa/fman_fdt.c optional dpaa fdt +dev/dpaa/fman_if.m optional dpaa +dev/dpaa/fman_mdio.c optional dpaa fdt +dev/dpaa/fman_port_if.m optional dpaa +dev/dpaa/fman_port.c optional dpaa +dev/dpaa/fman_xmdio.c optional dpaa fdt mdio miibus +dev/dpaa/dpaa_common.c optional dpaa +dev/dpaa/if_dtsec.c optional dpaa +dev/dpaa/if_dtsec_fdt.c optional dpaa fdt +dev/dpaa/if_memac.c optional dpaa +dev/dpaa/if_memac_fdt.c optional dpaa +dev/dpaa/portals_common.c optional dpaa +dev/dpaa/qman_portal_if.m optional dpaa +dev/dpaa/qman_portals.c optional dpaa fdt +dev/dpaa/qman.c optional dpaa +dev/dpaa/qman_fdt.c optional dpaa fdt dev/fb/fb.c optional sc dev/gpio/qoriq_gpio.c optional mpc85xx gpio dev/hwpmc/hwpmc_e500.c optional hwpmc diff --git a/sys/dev/dpaa/bman.c b/sys/dev/dpaa/bman.c index c275d2335eb8..90095427f10d 100644 --- a/sys/dev/dpaa/bman.c +++ b/sys/dev/dpaa/bman.c @@ -1,27 +1,7 @@ -/*- - * Copyright (c) 2011-2012 Semihalf. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. +/* + * SPDX-License-Identifier: BSD-2-Clause * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * Copyright (c) 2026 Justin Hibbits */ #include <sys/param.h> @@ -29,6 +9,7 @@ #include <sys/kernel.h> #include <sys/bus.h> #include <sys/lock.h> +#include <sys/malloc.h> #include <sys/module.h> #include <sys/mutex.h> #include <sys/proc.h> @@ -36,63 +17,161 @@ #include <sys/rman.h> #include <sys/sched.h> +#include <machine/bus.h> #include <machine/tlb.h> #include "bman.h" +#include "dpaa_common.h" +#include "bman_var.h" + +#define BMAN_POOL_SWDET(n) (0x000 + 4 * (n)) +#define BMAN_POOL_HWDET(n) (0x100 + 4 * (n)) +#define BMAN_POOL_SWDXT(n) (0x200 + 4 * (n)) +#define BMAN_POOL_HWDXT(n) (0x300 + 4 * (n)) +#define FBPR_FP_LWIT 0x804 +#define BMAN_IP_REV_1 0x0bf8 +#define IP_MAJ_S 8 +#define IP_MAJ_M 0x0000ff00 +#define IP_MIN_M 0x000000ff +#define BMAN_IP_REV_2 0x0bfc +#define BMAN_FBPR_BARE 0x0c00 +#define BMAN_FBPR_BAR 0x0c04 +#define BMAN_FBPR_AR 0x0c10 +#define BMAN_LIODNR 0x0d08 + +#define BMAN_POOL_CONTENT(n) (0x0600 + 4 * (n)) +#define BMAN_ECSR 0x0a00 +#define BMAN_ECIR 0x0a04 +#define ECIR_PORTAL(r) (((r) >> 24) & 0x0f) +#define ECIR_VERB(r) (((r) >> 16) & 0x07) +#define ECIR_R 0x00080000 +#define ECIR_POOL(r) ((r) & 0x3f) +#define BMAN_CECR 0x0a34 /* Corruption Error Capture Register */ +#define BMAN_CEAR 0x0a38 /* Corruption Error Address Register */ +#define BMAN_AECR 0x0a34 /* Acces Error Capture Register */ +#define BMAN_AEAR 0x0a38 /* Acces Error Address Register */ +#define BMAN_ERR_ISR 0x0e00 +#define BMAN_ERR_IER 0x0e04 +#define BMAN_ERR_ISDR 0x0e08 +#define ERR_EMAI 0x00000040 +#define ERR_EMCI 0x00000020 +#define ERR_IVCI 0x00000010 +#define ERR_FLWI 0x00000008 +#define ERR_MBEI 0x00000004 +#define ERR_SBEI 0x00000002 +#define ERR_BSCN 0x00000001 + +static MALLOC_DEFINE(M_BMAN, "bman", "DPAA Buffer Manager structures"); static struct bman_softc *bman_sc; -extern t_Handle bman_portal_setup(struct bman_softc *bsc); +static void +bman_isr(void *arg) +{ + struct bman_softc *sc = arg; + uint32_t ier, isr, isr_bit; + uint32_t reg; + + ier = bus_read_4(sc->sc_rres, BMAN_ERR_IER); + isr = bus_read_4(sc->sc_rres, BMAN_ERR_ISR); + + isr_bit = (isr & ier); + if (isr_bit == 0) + goto end; + + if (isr_bit & ERR_EMAI) { + device_printf(sc->sc_dev, "External memory access error\n"); + reg = bus_read_4(sc->sc_rres, BMAN_AECR); + if (reg <= 63) + device_printf(sc->sc_dev, " pool %d\n", reg); + else + device_printf(sc->sc_dev, " FBPR free list\n"); + reg = bus_read_4(sc->sc_rres, BMAN_AEAR); + device_printf(sc->sc_dev, " offset: %#x\n", reg); + } + + if (isr_bit & ERR_EMCI) { + device_printf(sc->sc_dev, "External memory corruption error\n"); + reg = bus_read_4(sc->sc_rres, BMAN_CECR); + if (reg <= 63) + device_printf(sc->sc_dev, " pool %d\n", reg); + else + device_printf(sc->sc_dev, " FBPR free list\n"); + reg = bus_read_4(sc->sc_rres, BMAN_CEAR); + device_printf(sc->sc_dev, " offset: %#x\n", reg); + } + if (isr_bit & ERR_IVCI) { + reg = bus_read_4(sc->sc_rres, BMAN_ECIR); + device_printf(sc->sc_dev, "Invalid verb command\n"); + device_printf(sc->sc_dev, "Portal: %d, ring: %s\n", + ECIR_POOL(reg), (reg & ECIR_R) ? "RCR" : "Command"); + device_printf(sc->sc_dev, "verb: 0x%02x, pool: %d\n", + ECIR_VERB(reg), ECIR_POOL(reg)); + } + if (isr_bit & (ERR_MBEI | ERR_SBEI)) { + if (isr_bit & ERR_MBEI) + device_printf(sc->sc_dev, "Multi-bit ECC error\n"); + if (isr_bit & ERR_MBEI) + device_printf(sc->sc_dev, "Single-bit ECC error\n"); + /* TODO: Add more error details for ECC errors. */ + } + +end: + bus_write_4(sc->sc_rres, BMAN_ERR_ISR, isr); +} static void -bman_exception(t_Handle h_App, e_BmExceptions exception) +bman_get_version(struct bman_softc *sc) { - struct bman_softc *sc; - const char *message; - - sc = h_App; - - switch (exception) { - case e_BM_EX_INVALID_COMMAND: - message = "Invalid Command Verb"; - break; - case e_BM_EX_FBPR_THRESHOLD: - message = "FBPR pool exhaused. Consider increasing " - "BMAN_MAX_BUFFERS"; - break; - case e_BM_EX_SINGLE_ECC: - message = "Single bit ECC error"; - break; - case e_BM_EX_MULTI_ECC: - message = "Multi bit ECC error"; - break; - default: - message = "Unknown error"; + uint32_t reg = bus_read_4(sc->sc_rres, BMAN_IP_REV_1); + + sc->sc_major = (reg & IP_MAJ_M) >> IP_MAJ_S; + sc->sc_minor = (reg & IP_MIN_M); +} + +static int +bman_set_memory(struct bman_softc *sc, vm_paddr_t pa, vm_size_t size) +{ + vm_paddr_t bar_pa; + if ((pa & (size - 1)) != 0 || (size & (size - 1)) != 0) { + device_printf(sc->sc_dev, + "invalid memory configuration: pa: %#jx, size: %#jx\n", + (uintmax_t)pa, (uintmax_t)size); + return (ENXIO); } + bar_pa = bus_read_4(sc->sc_rres, BMAN_FBPR_BARE); + bar_pa <<= 32; + bar_pa |= bus_read_4(sc->sc_rres, BMAN_FBPR_BAR); + if (bar_pa != 0 && bar_pa != pa) { + device_printf(sc->sc_dev, + "attempted to reinitialize BMan with different BAR\n"); + return (ENOMEM); + } else if (bar_pa == pa) + return (0); + + bus_write_4(sc->sc_rres, BMAN_FBPR_BARE, pa >> 32); + bus_write_4(sc->sc_rres, BMAN_FBPR_BAR, pa & 0xffffffff); + bus_write_4(sc->sc_rres, BMAN_FBPR_AR, ilog2(size) - 1); - device_printf(sc->sc_dev, "BMAN Exception: %s.\n", message); + return (0); } int bman_attach(device_t dev) { struct bman_softc *sc; - t_BmRevisionInfo rev; - t_Error error; - t_BmParam bp; + vm_paddr_t bp_pa; + size_t bp_size; + int bp_count; sc = device_get_softc(dev); sc->sc_dev = dev; bman_sc = sc; - /* Check if MallocSmart allocator is ready */ - if (XX_MallocSmartInit() != E_OK) - return (ENXIO); - /* Allocate resources */ sc->sc_rrid = 0; - sc->sc_rres = bus_alloc_resource_anywhere(dev, SYS_RES_MEMORY, - &sc->sc_rrid, BMAN_CCSR_SIZE, RF_ACTIVE); + sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + sc->sc_rrid, RF_ACTIVE); if (sc->sc_rres == NULL) return (ENXIO); @@ -102,36 +181,33 @@ bman_attach(device_t dev) if (sc->sc_ires == NULL) goto err; - /* Initialize BMAN */ - memset(&bp, 0, sizeof(bp)); - bp.guestId = NCSW_MASTER_ID; - bp.baseAddress = rman_get_bushandle(sc->sc_rres); - bp.totalNumOfBuffers = BMAN_MAX_BUFFERS; - bp.f_Exception = bman_exception; - bp.h_App = sc; - bp.errIrq = (uintptr_t)sc->sc_ires; - bp.partBpidBase = 0; - bp.partNumOfPools = BM_MAX_NUM_OF_POOLS; - - sc->sc_bh = BM_Config(&bp); - if (sc->sc_bh == NULL) - goto err; + bman_get_version(sc); + if (sc->sc_major == 2 && sc->sc_minor == 0) + bp_count = BMAN_MAX_POOLS_1023; + else + bp_count = BMAN_MAX_POOLS; - /* Warn if there is less than 5% free FPBR's in pool */ - error = BM_ConfigFbprThreshold(sc->sc_bh, (BMAN_MAX_BUFFERS / 8) / 20); - if (error != E_OK) - goto err; + /* TODO: LIODN */ + bus_write_4(sc->sc_rres, BMAN_LIODNR, 0); - error = BM_Init(sc->sc_bh); - if (error != E_OK) - goto err; + sc->sc_vmem = vmem_create("BMan Pools", 0, bp_count, 1, 0, M_WAITOK); - error = BM_GetRevision(sc->sc_bh, &rev); - if (error != E_OK) - goto err; + /* Pool is reserved memory, so no need to track it ourselves. */ + dpaa_map_private_memory(dev, 0, "fsl,bman-fbpr", &bp_pa, &bp_size); + bman_set_memory(sc, bp_pa, bp_size); + + /* Warn if FBPR drops below 5% total. */ + bus_write_4(sc->sc_rres, FBPR_FP_LWIT, (bp_size / 8) / 20); - device_printf(dev, "Hardware version: %d.%d.\n", - rev.majorRev, rev.minorRev); + /* Clear interrupt status, and enable all interrupts. */ + bus_write_4(sc->sc_rres, BMAN_ERR_ISR, 0xffffffff); + bus_write_4(sc->sc_rres, BMAN_ERR_IER, 0xffffffff); + bus_write_4(sc->sc_rres, BMAN_ERR_ISDR, 0); + + /* Enable the IRQ line now. */ + if (bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_NET, NULL, bman_isr, + sc, &sc->sc_icookie) != 0) + goto err; return (0); @@ -147,9 +223,10 @@ bman_detach(device_t dev) sc = device_get_softc(dev); - if (sc->sc_bh != NULL) - BM_Free(sc->sc_bh); - + if (sc->sc_vmem != NULL) + vmem_destroy(sc->sc_vmem); + if (sc->sc_icookie != NULL) + bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie); if (sc->sc_ires != NULL) bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires); @@ -186,179 +263,105 @@ bman_shutdown(device_t dev) * BMAN API */ -t_Handle -bman_pool_create(uint8_t *bpid, uint16_t bufferSize, uint16_t maxBuffers, - uint16_t minBuffers, uint16_t allocBuffers, t_GetBufFunction *f_GetBuf, - t_PutBufFunction *f_PutBuf, uint32_t dep_sw_entry, uint32_t dep_sw_exit, - uint32_t dep_hw_entry, uint32_t dep_hw_exit, - t_BmDepletionCallback *f_Depletion, t_Handle h_BufferPool, - t_PhysToVirt *f_PhysToVirt, t_VirtToPhys *f_VirtToPhys) +struct bman_pool * +bman_new_pool(void) { - uint32_t thresholds[MAX_DEPLETION_THRESHOLDS]; struct bman_softc *sc; - t_Handle pool, portal; - t_BmPoolParam bpp; - int error; + vmem_addr_t bpid; + struct bman_pool *pool; sc = bman_sc; pool = NULL; - sched_pin(); - - portal = bman_portal_setup(sc); - if (portal == NULL) - goto err; - - memset(&bpp, 0, sizeof(bpp)); - bpp.h_Bm = sc->sc_bh; - bpp.h_BmPortal = portal; - bpp.h_App = h_BufferPool; - bpp.numOfBuffers = allocBuffers; - - bpp.bufferPoolInfo.h_BufferPool = h_BufferPool; - bpp.bufferPoolInfo.f_GetBuf = f_GetBuf; - bpp.bufferPoolInfo.f_PutBuf = f_PutBuf; - bpp.bufferPoolInfo.f_PhysToVirt = f_PhysToVirt; - bpp.bufferPoolInfo.f_VirtToPhys = f_VirtToPhys; - bpp.bufferPoolInfo.bufferSize = bufferSize; - - pool = BM_POOL_Config(&bpp); - if (pool == NULL) - goto err; - - /* - * Buffer context must be disabled on FreeBSD - * as it could cause memory corruption. - */ - BM_POOL_ConfigBuffContextMode(pool, 0); - - if (minBuffers != 0 || maxBuffers != 0) { - error = BM_POOL_ConfigStockpile(pool, maxBuffers, minBuffers); - if (error != E_OK) - goto err; - } - - if (f_Depletion != NULL) { - thresholds[BM_POOL_DEP_THRESH_SW_ENTRY] = dep_sw_entry; - thresholds[BM_POOL_DEP_THRESH_SW_EXIT] = dep_sw_exit; - thresholds[BM_POOL_DEP_THRESH_HW_ENTRY] = dep_hw_entry; - thresholds[BM_POOL_DEP_THRESH_HW_EXIT] = dep_hw_exit; - error = BM_POOL_ConfigDepletion(pool, f_Depletion, thresholds); - if (error != E_OK) - goto err; - } - - error = BM_POOL_Init(pool); - if (error != E_OK) - goto err; + if (vmem_alloc(sc->sc_vmem, 1, M_FIRSTFIT | M_NOWAIT, &bpid) != 0) + return (NULL); - *bpid = BM_POOL_GetId(pool); - sc->sc_bpool_cpu[*bpid] = PCPU_GET(cpuid); + pool = malloc(sizeof(*pool), M_BMAN, M_WAITOK | M_ZERO); - sched_unpin(); + pool->bpid = bpid; return (pool); - -err: - if (pool != NULL) - BM_POOL_Free(pool); - - sched_unpin(); - - return (NULL); } -int -bman_pool_destroy(t_Handle pool) +struct bman_pool * +bman_pool_create(uint8_t *bpid, uint16_t buffer_size, uint16_t max_buffers, + uint32_t dep_sw_entry, uint32_t dep_sw_exit, + uint32_t dep_hw_entry, uint32_t dep_hw_exit, + bm_depletion_handler dep_cb, void *arg) { struct bman_softc *sc; + struct bman_pool *bp; sc = bman_sc; - thread_lock(curthread); - sched_bind(curthread, sc->sc_bpool_cpu[BM_POOL_GetId(pool)]); - thread_unlock(curthread); + bp = bman_new_pool(); + if (bpid != NULL) + *bpid = bp->bpid; + + if (dep_cb) { + bp->dep_cb = dep_cb; + bus_write_4(sc->sc_rres, BMAN_POOL_SWDET(bp->bpid), + dep_sw_entry); + bus_write_4(sc->sc_rres, BMAN_POOL_SWDXT(bp->bpid), + dep_sw_exit); + bus_write_4(sc->sc_rres, BMAN_POOL_HWDET(bp->bpid), + dep_hw_entry); + bus_write_4(sc->sc_rres, BMAN_POOL_HWDXT(bp->bpid), + dep_hw_exit); + bp->arg = arg; + bman_portal_enable_scn(DPCPU_GET(bman_affine_portal), bp); + } - BM_POOL_Free(pool); + return (bp); +} - thread_lock(curthread); - sched_unbind(curthread); - thread_unlock(curthread); +int +bman_pool_destroy(struct bman_pool *pool) +{ + /* Need to error, or print a warning, if the pool isn't empty */ + if (bman_count(pool) != 0) + return (EBUSY); + vmem_free(bman_sc->sc_vmem, pool->bpid, 1); + free(pool, M_BMAN); return (0); } int -bman_pool_fill(t_Handle pool, uint16_t nbufs) +bman_put_buffers(struct bman_pool *pool, struct bman_buffer *buffers, int count) { - struct bman_softc *sc; - t_Handle portal; + struct bman_portal_softc *portal; int error; - sc = bman_sc; - sched_pin(); + critical_enter(); - portal = bman_portal_setup(sc); + portal = DPCPU_GET(bman_affine_portal); if (portal == NULL) { - sched_unpin(); + critical_exit(); return (EIO); } - error = BM_POOL_FillBufs(pool, portal, nbufs); - - sched_unpin(); - - return ((error == E_OK) ? 0 : EIO); -} - -void * -bman_get_buffer(t_Handle pool) -{ - struct bman_softc *sc; - t_Handle portal; - void *buffer; - - sc = bman_sc; - sched_pin(); - - portal = bman_portal_setup(sc); - if (portal == NULL) { - sched_unpin(); - return (NULL); + while (count > 0) { + int c = min(count, 8); + error = bman_release(pool, buffers, c); + buffers += c; + count -= c; } - buffer = BM_POOL_GetBuf(pool, portal); + critical_exit(); - sched_unpin(); - - return (buffer); + return (error); } -int -bman_put_buffer(t_Handle pool, void *buffer) +uint32_t +bman_get_bpid(struct bman_pool *pool) { - struct bman_softc *sc; - t_Handle portal; - int error; - - sc = bman_sc; - sched_pin(); - - portal = bman_portal_setup(sc); - if (portal == NULL) { - sched_unpin(); - return (EIO); - } - - error = BM_POOL_PutBuf(pool, portal, buffer); - - sched_unpin(); - - return ((error == E_OK) ? 0 : EIO); + return (pool->bpid); } uint32_t -bman_count(t_Handle pool) +bman_count(struct bman_pool *pool) { - return (BM_POOL_GetCounter(pool, e_BM_POOL_COUNTERS_CONTENT)); + return (bus_read_4(bman_sc->sc_rres, BMAN_POOL_CONTENT(pool->bpid))); } + diff --git a/sys/dev/dpaa/bman.h b/sys/dev/dpaa/bman.h index 01c09489890c..d8a76bfa672b 100644 --- a/sys/dev/dpaa/bman.h +++ b/sys/dev/dpaa/bman.h @@ -1,3 +1,9 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2026 Justin Hibbits + */ + /*- * Copyright (c) 2011-2012 Semihalf. * All rights reserved. @@ -27,29 +33,16 @@ #ifndef _BMAN_H #define _BMAN_H +#include <sys/vmem.h> #include <machine/vmparam.h> -#include <contrib/ncsw/inc/Peripherals/bm_ext.h> - /* * BMAN Configuration */ -/* Maximum number of buffers in all BMAN pools */ -#define BMAN_MAX_BUFFERS 4096 - /* * Portal definitions */ -#define BMAN_CE_PA(base) (base) -#define BMAN_CI_PA(base) ((base) + 0x100000) - -#define BMAN_PORTAL_CE_PA(base, n) \ - (BMAN_CE_PA(base) + ((n) * BMAN_PORTAL_CE_SIZE)) -#define BMAN_PORTAL_CI_PA(base, n) \ - (BMAN_CI_PA(base) + ((n) * BMAN_PORTAL_CI_SIZE)) - -#define BMAN_CCSR_SIZE 0x1000 struct bman_softc { device_t sc_dev; /* device handle */ @@ -57,129 +50,42 @@ struct bman_softc { struct resource *sc_rres; /* register resource */ int sc_irid; /* interrupt rid */ struct resource *sc_ires; /* interrupt resource */ + void *sc_icookie; + vmem_t *sc_vmem; /* resource pool */ + int sc_major; + int sc_minor; +}; - bool sc_regs_mapped[MAXCPU]; /* register mapping status */ +struct bman_buffer { + uint16_t bpid; + uint16_t buf_hi; + uint32_t buf_lo; +} __aligned(8); - t_Handle sc_bh; /* BMAN handle */ - t_Handle sc_bph[MAXCPU]; /* BMAN portal handles */ - vm_paddr_t sc_bp_pa; /* BMAN portals PA */ - unsigned int sc_bpool_cpu[BM_MAX_NUM_OF_POOLS]; -}; +struct bman_pool; +struct bman_buffer; -/* - * External API - */ +typedef void (*bm_depletion_handler)(void *, bool); /* - * @brief Function to create BMAN pool. - * - * @param bpid The pointer to variable where Buffer Pool ID will be - * stored. - * - * @param bufferSize The size of buffers in newly created pool. - * - * @param maxBuffers The maximum number of buffers in software stockpile. - * Set to 0 if software stockpile should not be created. - * - * @param minBuffers The minimum number of buffers in software stockpile. - * Set to 0 if software stockpile should not be created. - * - * @param allocBuffers The number of buffers to preallocate during pool - * creation. - * - * @param f_GetBuf The buffer allocating function. Called only by - * bman_pool_create() and bman_pool_fill(). - * - * @param f_PutBuf The buffer freeing function. Called only by - * bman_pool_destroy(). - * - * @param dep_sw_entry The software portal depletion entry threshold. - * Set to 0 if depletion should not be signaled on - * software portal. - * - * @param dep_sw_exit The software portal depletion exit threshold. - * Set to 0 if depletion should not be signaled on - * software portal. - * - * @param dep_hw_entry The hardware portal depletion entry threshold. - * Set to 0 if depletion should not be signaled on - * hardware portal. - * - * @param dep_hw_exit The hardware portal depletion exit threshold. - * Set to 0 if depletion should not be signaled on - * hardware portal. - * - * @param f_Depletion The software portal depletion notification function. - * Set to NULL if depletion notification is not used. - * - * @param h_BufferPool The user provided buffer pool context passed to - * f_GetBuf, f_PutBuf and f_Depletion functions. - * - * @param f_PhysToVirt The PA to VA translation function. Set to NULL if - * default one should be used. - * - * @param f_VirtToPhys The VA to PA translation function. Set to NULL if - * default one should be used. - * - * @returns Handle to newly created BMAN pool or NULL on error. - * - * @cautions If pool uses software stockpile, all accesses to given - * pool must be protected by lock. Even if only hardware - * portal depletion notification is used, the caller must - * provide valid @p f_Depletion function. + * External API */ -t_Handle bman_pool_create(uint8_t *bpid, uint16_t bufferSize, - uint16_t maxBuffers, uint16_t minBuffers, uint16_t allocBuffers, - t_GetBufFunction *f_GetBuf, t_PutBufFunction *f_PutBuf, - uint32_t dep_sw_entry, uint32_t dep_sw_exit, uint32_t dep_hw_entry, - uint32_t dep_hw_exit, t_BmDepletionCallback *f_Depletion, - t_Handle h_BufferPool, t_PhysToVirt *f_PhysToVirt, - t_VirtToPhys *f_VirtToPhys); -/* - * @brief Fill pool with buffers. - * - * The bman_pool_fill() function fills the BMAN pool with buffers. The buffers - * are allocated through f_GetBuf function (see bman_pool_create() description). - * - * @param pool The BMAN pool handle. - * @param nbufs The number of buffers to allocate. To maximize - * performance this value should be multiple of 8. - * - * @returns Zero on success or error code on failure. - */ -int bman_pool_fill(t_Handle pool, uint16_t nbufs); +struct bman_pool *bman_new_pool(void); +struct bman_pool *bman_pool_create(uint8_t *bpid, uint16_t buffer_size, + uint16_t max_buffers, uint32_t dep_sw_entry, uint32_t dep_sw_exit, uint32_t + dep_hw_entry, uint32_t dep_hw_exit, bm_depletion_handler dep_cb, void *arg); /* * @brief Destroy pool. * - * The bman_pool_destroy() function destroys the BMAN pool. Buffers for pool - * are free through f_PutBuf function (see bman_pool_create() description). + * The bman_pool_destroy() function destroys the BMAN pool. + * The buffer pool must be empty. * * @param pool The BMAN pool handle. - * - * @returns Zero on success or error code on failure. - */ -int bman_pool_destroy(t_Handle pool); - -/* - * @brief Get a buffer from BMAN pool. - * - * @param pool The BMAN pool handle. - * - * @returns Pointer to the buffer or NULL if pool is empty. - */ -void *bman_get_buffer(t_Handle pool); - -/* - * @brief Put a buffer to BMAN pool. - * - * @param pool The BMAN pool handle. - * @param buffer The pointer to buffer. - * - * @returns Zero on success or error code on failure. + * @return 0 on success, EBUSY if the pool is not empty. */ -int bman_put_buffer(t_Handle pool, void *buffer); +int bman_pool_destroy(struct bman_pool *pool); /* * @brief Count free buffers in given pool. @@ -188,7 +94,25 @@ int bman_put_buffer(t_Handle pool, void *buffer); * * @returns Number of free buffers in pool. */ -uint32_t bman_count(t_Handle pool); +uint32_t bman_count(struct bman_pool *pool); + +int bman_put_buffers(struct bman_pool *, struct bman_buffer *, int); +static inline int +bman_put_buffer(struct bman_pool *p, vm_paddr_t buf, int bpid) +{ + struct bman_buffer b = { + .bpid = bpid, + .buf_hi = ((uintptr_t)buf) >> 32, + .buf_lo = ((uintptr_t)buf) & 0xffffffff + }; + return (bman_put_buffers(p, &b, 1)); +} + +int bman_acquire(struct bman_pool *, struct bman_buffer *, uint8_t); + +int bman_create_affine_portal(device_t, vm_offset_t, vm_offset_t, int); +void bman_destroy_affine_portal(int); +uint32_t bman_get_bpid(struct bman_pool *); /* * Bus i/f diff --git a/sys/dev/dpaa/bman_fdt.c b/sys/dev/dpaa/bman_fdt.c index 330db7b89715..c77d58cf118d 100644 --- a/sys/dev/dpaa/bman_fdt.c +++ b/sys/dev/dpaa/bman_fdt.c @@ -40,6 +40,7 @@ #include <dev/ofw/ofw_subr.h> #include "bman.h" +#include "bman_var.h" #include "portals.h" #define FBMAN_DEVSTR "Freescale Buffer Manager" @@ -59,12 +60,7 @@ static device_method_t bman_methods[] = { DEVMETHOD_END }; -static driver_t bman_driver = { - "bman", - bman_methods, - sizeof(struct bman_softc), -}; - +DEFINE_CLASS_0(bman, bman_driver, bman_methods, sizeof(struct bman_softc)); EARLY_DRIVER_MODULE(bman, simplebus, bman_driver, 0, 0, BUS_PASS_SUPPORTDEV); static int @@ -82,144 +78,46 @@ bman_fdt_probe(device_t dev) /* * BMAN Portals */ -#define BMAN_PORT_DEVSTR "Freescale Buffer Manager - Portals" +#define BMAN_PORT_DEVSTR "Freescale Buffer Manager - Portal" -static device_probe_t bman_portals_fdt_probe; -static device_attach_t bman_portals_fdt_attach; +static int portal_ncpus; +static device_probe_t bman_portal_fdt_probe; +static device_attach_t bman_portal_fdt_attach; -static device_method_t bm_portals_methods[] = { +static device_method_t bman_portal_methods[] = { /* Device interface */ - DEVMETHOD(device_probe, bman_portals_fdt_probe), - DEVMETHOD(device_attach, bman_portals_fdt_attach), - DEVMETHOD(device_detach, bman_portals_detach), + DEVMETHOD(device_probe, bman_portal_fdt_probe), + DEVMETHOD(device_attach, bman_portal_fdt_attach), + DEVMETHOD(device_detach, bman_portal_detach), DEVMETHOD_END }; -static driver_t bm_portals_driver = { - "bman-portals", - bm_portals_methods, - sizeof(struct dpaa_portals_softc), -}; - -EARLY_DRIVER_MODULE(bman_portals, ofwbus, bm_portals_driver, 0, 0, - BUS_PASS_BUS); - -static void -get_addr_props(phandle_t node, uint32_t *addrp, uint32_t *sizep) -{ - - *addrp = 2; - *sizep = 1; - OF_getencprop(node, "#address-cells", addrp, sizeof(*addrp)); - OF_getencprop(node, "#size-cells", sizep, sizeof(*sizep)); -} +DEFINE_CLASS_0(bman_portal, bman_portal_driver, bman_portal_methods, + sizeof(struct bman_portal_softc)); +EARLY_DRIVER_MODULE(bman_portal, simplebus, bman_portal_driver, 0, 0, + BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_MIDDLE); static int -bman_portals_fdt_probe(device_t dev) +bman_portal_fdt_probe(device_t dev) { - phandle_t node; - - if (ofw_bus_is_compatible(dev, "simple-bus")) { *** 9976 LINES SKIPPED ***home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69f79dfd.3d681.162b0f5>
