The branch main has been updated by dsl: URL: https://cgit.FreeBSD.org/src/commit/?id=8e994533806d8aa0ae4582a52d811ede2b19bb26
commit 8e994533806d8aa0ae4582a52d811ede2b19bb26 Author: Dmitry Salychev <[email protected]> AuthorDate: 2026-01-25 16:53:57 +0000 Commit: Dmitry Salychev <[email protected]> CommitDate: 2026-04-08 19:48:11 +0000 dpaa2: Extract frame-specific routines to dpaa2_frame.[h,c] As soon as we need information from the hardware frame annotation to make sure that checksums of the ingress frames were verified by the DPAA2 HW, I've decided to make a preparation and extracted all of the frame related routines into the separate dpaa2_frame.[h,c] along with some clean up and improvements, e.g. no more dpaa2_fa, but dpaa2_swa and dpaa2_hwa structures to describe software and hardware frame annotations respectively, dpaa2_fa_get_swa/dpaa2_fa_get_hwa to obtain those annotations from the frame descriptor. The next step is to implement dpaa2_fa_get_hwa. PR: 292006 Approved by: tuexen MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D56315 --- sys/conf/files.arm64 | 1 + sys/dev/dpaa2/dpaa2_buf.c | 9 +- sys/dev/dpaa2/dpaa2_buf.h | 2 + sys/dev/dpaa2/dpaa2_frame.c | 165 ++++++++++++++++++++++++++++++++++ sys/dev/dpaa2/dpaa2_frame.h | 174 ++++++++++++++++++++++++++++++++++++ sys/dev/dpaa2/dpaa2_ni.c | 210 ++++++++++++++------------------------------ sys/dev/dpaa2/dpaa2_ni.h | 3 +- sys/dev/dpaa2/dpaa2_swp.h | 51 +---------- sys/dev/dpaa2/dpaa2_types.h | 5 ++ sys/modules/dpaa2/Makefile | 1 + 10 files changed, 420 insertions(+), 201 deletions(-) diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 index 2a607748db8d..59a65a8251ca 100644 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -262,6 +262,7 @@ dev/dpaa2/dpaa2_channel.c optional soc_nxp_ls dpaa2 dev/dpaa2/dpaa2_cmd_if.m optional soc_nxp_ls dpaa2 dev/dpaa2/dpaa2_con.c optional soc_nxp_ls dpaa2 dev/dpaa2/dpaa2_console.c optional soc_nxp_ls dpaa2 fdt +dev/dpaa2/dpaa2_frame.c optional soc_nxp_ls dpaa2 dev/dpaa2/dpaa2_io.c optional soc_nxp_ls dpaa2 dev/dpaa2/dpaa2_mac.c optional soc_nxp_ls dpaa2 dev/dpaa2/dpaa2_mc.c optional soc_nxp_ls dpaa2 diff --git a/sys/dev/dpaa2/dpaa2_buf.c b/sys/dev/dpaa2/dpaa2_buf.c index 8505b074fe4f..228e4448210d 100644 --- a/sys/dev/dpaa2/dpaa2_buf.c +++ b/sys/dev/dpaa2/dpaa2_buf.c @@ -42,6 +42,7 @@ #include "dpaa2_swp.h" #include "dpaa2_swp_if.h" #include "dpaa2_ni.h" +#include "dpaa2_frame.h" MALLOC_DEFINE(M_DPAA2_RXB, "dpaa2_rxb", "DPAA2 DMA-mapped buffer (Rx)"); @@ -129,7 +130,7 @@ dpaa2_buf_seed_rxb(device_t dev, struct dpaa2_buf *buf, int size, struct mtx *dma_mtx) { struct dpaa2_ni_softc *sc = device_get_softc(dev); - struct dpaa2_fa *fa; + struct dpaa2_swa *swa; bool map_created = false; bool mbuf_alloc = false; int error; @@ -179,9 +180,9 @@ dpaa2_buf_seed_rxb(device_t dev, struct dpaa2_buf *buf, int size, buf->vaddr = buf->m->m_data; /* Populate frame annotation for future use */ - fa = (struct dpaa2_fa *)buf->vaddr; - fa->magic = DPAA2_MAGIC; - fa->buf = buf; + swa = (struct dpaa2_swa *)buf->vaddr; + swa->magic = DPAA2_MAGIC; + swa->buf = buf; bus_dmamap_sync(buf->dmat, buf->dmap, BUS_DMASYNC_PREREAD); diff --git a/sys/dev/dpaa2/dpaa2_buf.h b/sys/dev/dpaa2/dpaa2_buf.h index 853a4fa78d3a..16ea7e1905ac 100644 --- a/sys/dev/dpaa2/dpaa2_buf.h +++ b/sys/dev/dpaa2/dpaa2_buf.h @@ -33,6 +33,8 @@ #include <sys/malloc.h> #include <sys/lock.h> #include <sys/mutex.h> +#include <sys/systm.h> +#include <sys/mbuf.h> #include <machine/bus.h> diff --git a/sys/dev/dpaa2/dpaa2_frame.c b/sys/dev/dpaa2/dpaa2_frame.c new file mode 100644 index 000000000000..4a155f7cb32f --- /dev/null +++ b/sys/dev/dpaa2/dpaa2_frame.c @@ -0,0 +1,165 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright © 2026 Dmitry Salychev + * + * 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. + * + * 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. + */ + +#include <sys/cdefs.h> + +#include <sys/param.h> +#include <sys/errno.h> + +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <machine/vmparam.h> + +#include "dpaa2_types.h" +#include "dpaa2_frame.h" +#include "dpaa2_buf.h" +#include "dpaa2_swp.h" + +/** + * @brief Build a DPAA2 frame descriptor. + */ +int +dpaa2_fd_build(device_t dev, const uint16_t tx_data_off, struct dpaa2_buf *buf, + bus_dma_segment_t *segs, const int nsegs, struct dpaa2_fd *fd) +{ + struct dpaa2_buf *sgt = buf->sgt; + struct dpaa2_sg_entry *sge; + struct dpaa2_swa *swa; + int i, error; + + if (buf == NULL || segs == NULL || nsegs == 0 || fd == NULL) + return (EINVAL); + + KASSERT(nsegs <= DPAA2_TX_SEGLIMIT, ("%s: too many segments", __func__)); + KASSERT(buf->opt != NULL, ("%s: no Tx ring?", __func__)); + KASSERT(sgt != NULL, ("%s: no S/G table?", __func__)); + KASSERT(sgt->vaddr != NULL, ("%s: no S/G vaddr?", __func__)); + + memset(fd, 0, sizeof(*fd)); + + /* Populate and map S/G table */ + if (__predict_true(nsegs <= DPAA2_TX_SEGLIMIT)) { + sge = (struct dpaa2_sg_entry *)sgt->vaddr + tx_data_off; + for (i = 0; i < nsegs; i++) { + sge[i].addr = (uint64_t)segs[i].ds_addr; + sge[i].len = (uint32_t)segs[i].ds_len; + sge[i].offset_fmt = 0u; + } + sge[i-1].offset_fmt |= 0x8000u; /* set final entry flag */ + + KASSERT(sgt->paddr == 0, ("%s: paddr(%#jx) != 0", __func__, + sgt->paddr)); + + error = bus_dmamap_load(sgt->dmat, sgt->dmap, sgt->vaddr, + DPAA2_TX_SGT_SZ, dpaa2_dmamap_oneseg_cb, &sgt->paddr, + BUS_DMA_NOWAIT); + if (__predict_false(error != 0)) { + device_printf(dev, "%s: bus_dmamap_load() failed: " + "error=%d\n", __func__, error); + return (error); + } + + buf->paddr = sgt->paddr; + buf->vaddr = sgt->vaddr; + } else { + return (EINVAL); + } + + swa = (struct dpaa2_swa *)sgt->vaddr; + swa->magic = DPAA2_MAGIC; + swa->buf = buf; + + fd->addr = buf->paddr; + fd->data_length = (uint32_t)buf->m->m_pkthdr.len; + fd->bpid_ivp_bmt = 0; + fd->offset_fmt_sl = 0x2000u | tx_data_off; + fd->ctrl = (0x4u & DPAA2_FD_PTAC_MASK) << DPAA2_FD_PTAC_SHIFT; + + return (0); +} + +int +dpaa2_fd_err(struct dpaa2_fd *fd) +{ + return ((fd->ctrl >> DPAA2_FD_ERR_SHIFT) & DPAA2_FD_ERR_MASK); +} + +uint32_t +dpaa2_fd_data_len(struct dpaa2_fd *fd) +{ + if (dpaa2_fd_short_len(fd)) { + return (fd->data_length & DPAA2_FD_LEN_MASK); + } + return (fd->data_length); +} + +int +dpaa2_fd_format(struct dpaa2_fd *fd) +{ + return ((enum dpaa2_fd_format)((fd->offset_fmt_sl >> + DPAA2_FD_FMT_SHIFT) & DPAA2_FD_FMT_MASK)); +} + +bool +dpaa2_fd_short_len(struct dpaa2_fd *fd) +{ + return (((fd->offset_fmt_sl >> DPAA2_FD_SL_SHIFT) + & DPAA2_FD_SL_MASK) == 1); +} + +int +dpaa2_fd_offset(struct dpaa2_fd *fd) +{ + return (fd->offset_fmt_sl & DPAA2_FD_OFFSET_MASK); +} + +int +dpaa2_fa_get_swa(struct dpaa2_fd *fd, struct dpaa2_swa **swa) +{ + int rc; + + if (fd == NULL || swa == NULL) + return (EINVAL); + + if (((fd->ctrl >> DPAA2_FD_PTAC_SHIFT) & DPAA2_FD_PTAC_MASK) >= 0x4u) { + *swa = (struct dpaa2_swa *)PHYS_TO_DMAP((bus_addr_t)fd->addr); + rc = 0; + } else { + *swa = NULL; + rc = ENOENT; + } + + return (rc); +} + +int +dpaa2_fa_get_hwa(struct dpaa2_fd *fd, struct dpaa2_hwa **hwa) +{ + /* TODO: To be implemented next. */ + return (ENOENT); +} diff --git a/sys/dev/dpaa2/dpaa2_frame.h b/sys/dev/dpaa2/dpaa2_frame.h new file mode 100644 index 000000000000..0b2a5a7d8e74 --- /dev/null +++ b/sys/dev/dpaa2/dpaa2_frame.h @@ -0,0 +1,174 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright © 2026 Dmitry Salychev + * + * 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. + * + * 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. + */ + +#ifndef _DPAA2_FRAME_H +#define _DPAA2_FRAME_H + +#include <sys/types.h> +#include <sys/bus.h> +#include <sys/kassert.h> + +#include "dpaa2_types.h" +#include "dpaa2_buf.h" + +/* + * Helper routines for the DPAA2 frames (e.g. descriptors, software/hardware + * annotations, etc.). + */ + +/* + * DPAA2 frame descriptor size, field offsets and masks. + * + * See 3.1.1 Frame descriptor format, + * 4.2.1.2.2 Structure of Frame Descriptors (FDs), + * LX2160A DPAA2 Low-Level Hardware Reference Manual, Rev. 0, 06/2020 + */ +#define DPAA2_FD_SIZE 32u +#define DPAA2_FD_FMT_MASK (0x3u) +#define DPAA2_FD_FMT_SHIFT (12) +#define DPAA2_FD_ERR_MASK (0xFFu) +#define DPAA2_FD_ERR_SHIFT (0) +#define DPAA2_FD_SL_MASK (0x1u) +#define DPAA2_FD_SL_SHIFT (14) +#define DPAA2_FD_LEN_MASK (0x3FFFFu) +#define DPAA2_FD_OFFSET_MASK (0x0FFFu) +#define DPAA2_FD_PTAC_MASK (0x7u) +#define DPAA2_FD_PTAC_SHIFT (21) + +/* + * DPAA2 frame annotation sizes + * + * NOTE: Accelerator-specific (HWA) annotation length is described in the 64-byte + * units by the FD[ASAL] bits and can be as big as 960 bytes. Current + * values describe what is actually supported by the DPAA2 drivers. + * + * See 3.1.1 Frame descriptor format, + * LX2160A DPAA2 Low-Level Hardware Reference Manual, Rev. 0 + */ +#define DPAA2_FA_SIZE 192u /* DPAA2 frame annotation */ +#define DPAA2_FA_SWA_SIZE 64u /* SW frame annotation */ +#define DPAA2_FA_HWA_SIZE 128u /* HW frame annotation */ +#define DPAA2_FA_WRIOP_SIZE 128u /* WRIOP HW annotation */ + +/** + * @brief DPAA2 frame descriptor. + * + * addr: Memory address of the start of the buffer holding the + * frame data or the buffer containing the scatter/gather + * list. + * data_length: Length of the frame data (in bytes). + * bpid_ivp_bmt: Buffer pool ID (14 bit + BMT bit + IVP bit) + * offset_fmt_sl: Frame data offset, frame format and short-length fields. + * frame_ctx: Frame context. This field allows the sender of a frame + * to communicate some out-of-band information to the + * receiver of the frame. + * ctrl: Control bits (ERR, CBMT, ASAL, PTAC, DROPP, SC, DD). + * flow_ctx: Frame flow context. Associates the frame with a flow + * structure. QMan may use the FLC field for 3 purposes: + * stashing control, order definition point identification, + * and enqueue replication control. + * + * See 3.1.1 Frame descriptor format, + * 4.2.1.2.2 Structure of Frame Descriptors (FDs), + * LX2160A DPAA2 Low-Level Hardware Reference Manual, Rev. 0, 06/2020 + */ +struct dpaa2_fd { + uint64_t addr; + uint32_t data_length; + uint16_t bpid_ivp_bmt; + uint16_t offset_fmt_sl; + uint32_t frame_ctx; + uint32_t ctrl; + uint64_t flow_ctx; +} __packed; +CTASSERT(sizeof(struct dpaa2_fd) == DPAA2_FD_SIZE); + +/** + * @brief WRIOP hardware frame annotation. + * + * See 7.34.2 WRIOP hardware frame annotation (FA), + * LX2160A DPAA2 Low-Level Hardware Reference Manual, Rev. 0, 06/2020 + */ +struct dpaa2_hwa_wriop { + union { + struct { + uint64_t fas; + uint64_t timestamp; + /* XXX-DSL: more to add here... */ + } __packed; + uint8_t raw[128]; + }; +} __packed; +CTASSERT(sizeof(struct dpaa2_hwa_wriop) == DPAA2_FA_WRIOP_SIZE); + +/** + * @brief DPAA2 hardware frame annotation (accelerator-specific annotation). + * + * See 3.4.1.2 Accelerator-specific annotation, + * LX2160A DPAA2 Low-Level Hardware Reference Manual, Rev. 0, 06/2020 + */ +struct dpaa2_hwa { + union { + struct dpaa2_hwa_wriop wriop; + }; +} __packed; +CTASSERT(sizeof(struct dpaa2_hwa) == DPAA2_FA_HWA_SIZE); + +/** + * @brief DPAA2 software frame annotation (pass-through annotation). + * + * See 3.4.1.1 Pass-through annotation, + * LX2160A DPAA2 Low-Level Hardware Reference Manual, Rev. 0, 06/2020 + */ +struct dpaa2_swa { + union { + struct { + uint32_t magic; + struct dpaa2_buf *buf; + }; + struct { + uint8_t pta1[32]; + uint8_t pta2[32]; + }; + uint8_t raw[64]; + }; +} __packed; +CTASSERT(sizeof(struct dpaa2_swa) == DPAA2_FA_SWA_SIZE); + +int dpaa2_fd_build(device_t, const uint16_t, struct dpaa2_buf *, + bus_dma_segment_t *, const int, struct dpaa2_fd *); + +int dpaa2_fd_err(struct dpaa2_fd *); +uint32_t dpaa2_fd_data_len(struct dpaa2_fd *); +int dpaa2_fd_format(struct dpaa2_fd *); +bool dpaa2_fd_short_len(struct dpaa2_fd *); +int dpaa2_fd_offset(struct dpaa2_fd *); + +int dpaa2_fa_get_swa(struct dpaa2_fd *, struct dpaa2_swa **); +int dpaa2_fa_get_hwa(struct dpaa2_fd *, struct dpaa2_hwa **); + +#endif /* _DPAA2_FRAME_H */ diff --git a/sys/dev/dpaa2/dpaa2_ni.c b/sys/dev/dpaa2/dpaa2_ni.c index 49e72c8ee14f..5017b5113109 100644 --- a/sys/dev/dpaa2/dpaa2_ni.c +++ b/sys/dev/dpaa2/dpaa2_ni.c @@ -96,6 +96,7 @@ #include "dpaa2_ni.h" #include "dpaa2_channel.h" #include "dpaa2_buf.h" +#include "dpaa2_frame.h" #define BIT(x) (1ul << (x)) #define WRIOP_VERSION(x, y, z) ((x) << 10 | (y) << 5 | (z) << 0) @@ -156,10 +157,6 @@ MALLOC_DEFINE(M_DPAA2_TXB, "dpaa2_txb", "DPAA2 DMA-mapped buffer (Tx)"); #define DPAA2_RX_BUFRING_SZ (4096u) #define DPAA2_RXE_BUFRING_SZ (1024u) #define DPAA2_TXC_BUFRING_SZ (4096u) -#define DPAA2_TX_SEGLIMIT (16u) /* arbitrary number */ -#define DPAA2_TX_SEG_SZ (PAGE_SIZE) -#define DPAA2_TX_SEGS_MAXSZ (DPAA2_TX_SEGLIMIT * DPAA2_TX_SEG_SZ) -#define DPAA2_TX_SGT_SZ (PAGE_SIZE) /* bytes */ /* Size of a buffer to keep a QoS table key configuration. */ #define ETH_QOS_KCFG_BUF_SIZE (PAGE_SIZE) @@ -186,15 +183,6 @@ MALLOC_DEFINE(M_DPAA2_TXB, "dpaa2_txb", "DPAA2 DMA-mapped buffer (Tx)"); #define DPAA2_NI_TXBUF_IDX_MASK (0xFFu) #define DPAA2_NI_TXBUF_IDX_SHIFT (49) -#define DPAA2_NI_FD_FMT_MASK (0x3u) -#define DPAA2_NI_FD_FMT_SHIFT (12) -#define DPAA2_NI_FD_ERR_MASK (0xFFu) -#define DPAA2_NI_FD_ERR_SHIFT (0) -#define DPAA2_NI_FD_SL_MASK (0x1u) -#define DPAA2_NI_FD_SL_SHIFT (14) -#define DPAA2_NI_FD_LEN_MASK (0x3FFFFu) -#define DPAA2_NI_FD_OFFSET_MASK (0x0FFFu) - /* Enables TCAM for Flow Steering and QoS look-ups. */ #define DPNI_OPT_HAS_KEY_MASKING 0x10 @@ -424,15 +412,6 @@ static int dpaa2_ni_set_mac_addr(device_t); static int dpaa2_ni_set_hash(device_t, uint64_t); static int dpaa2_ni_set_dist_key(device_t, enum dpaa2_ni_dist_mode, uint64_t); -/* Frame descriptor routines */ -static int dpaa2_ni_build_fd(struct dpaa2_ni_softc *, struct dpaa2_ni_tx_ring *, - struct dpaa2_buf *, bus_dma_segment_t *, int, struct dpaa2_fd *); -static int dpaa2_ni_fd_err(struct dpaa2_fd *); -static uint32_t dpaa2_ni_fd_data_len(struct dpaa2_fd *); -static int dpaa2_ni_fd_format(struct dpaa2_fd *); -static bool dpaa2_ni_fd_short_len(struct dpaa2_fd *); -static int dpaa2_ni_fd_offset(struct dpaa2_fd *); - /* Various subroutines */ static int dpaa2_ni_cmp_api_version(struct dpaa2_ni_softc *, uint16_t, uint16_t); static int dpaa2_ni_prepare_key_cfg(struct dpkg_profile_cfg *, uint8_t *); @@ -2995,14 +2974,15 @@ dpaa2_ni_tx(struct dpaa2_ni_softc *sc, struct dpaa2_channel *ch, } } - error = dpaa2_ni_build_fd(sc, tx, buf, segs, nsegs, &fd); + error = dpaa2_fd_build(dev, sc->tx_data_off, buf, segs, nsegs, &fd); if (__predict_false(error != 0)) { device_printf(dev, "%s: failed to build frame descriptor: " "error=%d\n", __func__, error); fq->chan->tx_dropped++; if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1); goto err_unload; - } + } else + sc->tx_sg_frames++; /* for sysctl(9) */ bus_dmamap_sync(buf->dmat, buf->dmap, BUS_DMASYNC_PREWRITE); bus_dmamap_sync(sgt->dmat, sgt->dmap, BUS_DMASYNC_PREWRITE); @@ -3130,14 +3110,14 @@ dpaa2_ni_consume_frames(struct dpaa2_channel *chan, struct dpaa2_ni_fq **src, * @brief Receive frames. */ static int -dpaa2_ni_rx(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq, struct dpaa2_fd *fd, - struct dpaa2_ni_rx_ctx *ctx) +dpaa2_ni_rx(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq, + struct dpaa2_fd *fd, struct dpaa2_ni_rx_ctx *ctx) { - bus_addr_t paddr = (bus_addr_t)fd->addr; - struct dpaa2_fa *fa = (struct dpaa2_fa *)PHYS_TO_DMAP(paddr); - struct dpaa2_buf *buf = fa->buf; - struct dpaa2_channel *bch = (struct dpaa2_channel *)buf->opt; - struct dpaa2_ni_softc *sc = device_get_softc(bch->ni_dev); + bus_addr_t paddr; + struct dpaa2_swa *swa; + struct dpaa2_buf *buf; + struct dpaa2_channel *bch; + struct dpaa2_ni_softc *sc; struct dpaa2_bp_softc *bpsc; struct mbuf *m; device_t bpdev; @@ -3145,7 +3125,17 @@ dpaa2_ni_rx(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq, struct dpaa2_fd *f void *buf_data; int buf_len, error, released_n = 0; - KASSERT(fa->magic == DPAA2_MAGIC, ("%s: wrong magic", __func__)); + error = dpaa2_fa_get_swa(fd, &swa); + if (__predict_false(error != 0)) + panic("%s: frame has no software annotation: error=%d", + __func__, error); + + paddr = (bus_addr_t)fd->addr; + buf = swa->buf; + bch = (struct dpaa2_channel *)buf->opt; + sc = device_get_softc(bch->ni_dev); + + KASSERT(swa->magic == DPAA2_MAGIC, ("%s: wrong magic", __func__)); /* * NOTE: Current channel might not be the same as the "buffer" channel * and it's fine. It must not be NULL though. @@ -3157,7 +3147,7 @@ dpaa2_ni_rx(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq, struct dpaa2_fd *f __func__, paddr, buf->paddr); } - switch (dpaa2_ni_fd_err(fd)) { + switch (dpaa2_fd_err(fd)) { case 1: /* Enqueue rejected by QMan */ sc->rx_enq_rej_frames++; break; @@ -3167,7 +3157,7 @@ dpaa2_ni_rx(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq, struct dpaa2_fd *f default: break; } - switch (dpaa2_ni_fd_format(fd)) { + switch (dpaa2_fd_format(fd)) { case DPAA2_FD_SINGLE: sc->rx_single_buf_frames++; break; @@ -3183,9 +3173,11 @@ dpaa2_ni_rx(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq, struct dpaa2_fd *f bus_dmamap_sync(buf->dmat, buf->dmap, BUS_DMASYNC_POSTREAD); bus_dmamap_unload(buf->dmat, buf->dmap); + m = buf->m; - buf_len = dpaa2_ni_fd_data_len(fd); - buf_data = (uint8_t *)buf->vaddr + dpaa2_ni_fd_offset(fd); + buf_len = dpaa2_fd_data_len(fd); + buf_data = (uint8_t *)buf->vaddr + dpaa2_fd_offset(fd); + /* Prepare buffer to be re-cycled */ buf->m = NULL; buf->paddr = 0; @@ -3273,16 +3265,26 @@ static int dpaa2_ni_rx_err(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq, struct dpaa2_fd *fd) { - bus_addr_t paddr = (bus_addr_t)fd->addr; - struct dpaa2_fa *fa = (struct dpaa2_fa *)PHYS_TO_DMAP(paddr); - struct dpaa2_buf *buf = fa->buf; - struct dpaa2_channel *bch = (struct dpaa2_channel *)buf->opt; - struct dpaa2_ni_softc *sc = device_get_softc(bch->ni_dev); + bus_addr_t paddr; + struct dpaa2_swa *swa; + struct dpaa2_buf *buf; + struct dpaa2_channel *bch; + struct dpaa2_ni_softc *sc; device_t bpdev; struct dpaa2_bp_softc *bpsc; int error; - KASSERT(fa->magic == DPAA2_MAGIC, ("%s: wrong magic", __func__)); + error = dpaa2_fa_get_swa(fd, &swa); + if (__predict_false(error != 0)) + panic("%s: frame has no software annotation: error=%d", + __func__, error); + + paddr = (bus_addr_t)fd->addr; + buf = swa->buf; + bch = (struct dpaa2_channel *)buf->opt; + sc = device_get_softc(bch->ni_dev); + + KASSERT(swa->magic == DPAA2_MAGIC, ("%s: wrong magic", __func__)); /* * NOTE: Current channel might not be the same as the "buffer" channel * and it's fine. It must not be NULL though. @@ -3316,14 +3318,26 @@ static int dpaa2_ni_tx_conf(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq, struct dpaa2_fd *fd) { - bus_addr_t paddr = (bus_addr_t)fd->addr; - struct dpaa2_fa *fa = (struct dpaa2_fa *)PHYS_TO_DMAP(paddr); - struct dpaa2_buf *buf = fa->buf; - struct dpaa2_buf *sgt = buf->sgt; - struct dpaa2_ni_tx_ring *tx = (struct dpaa2_ni_tx_ring *)buf->opt; - struct dpaa2_channel *bch = tx->fq->chan; - - KASSERT(fa->magic == DPAA2_MAGIC, ("%s: wrong magic", __func__)); + bus_addr_t paddr; + struct dpaa2_swa *swa; + struct dpaa2_buf *buf; + struct dpaa2_buf *sgt; + struct dpaa2_ni_tx_ring *tx; + struct dpaa2_channel *bch; + int error; + + error = dpaa2_fa_get_swa(fd, &swa); + if (__predict_false(error != 0)) + panic("%s: frame has no software annotation: error=%d", + __func__, error); + + paddr = (bus_addr_t)fd->addr; + buf = swa->buf; + sgt = buf->sgt; + tx = (struct dpaa2_ni_tx_ring *)buf->opt; + bch = tx->fq->chan; + + KASSERT(swa->magic == DPAA2_MAGIC, ("%s: wrong magic", __func__)); KASSERT(tx != NULL, ("%s: Tx ring is NULL", __func__)); KASSERT(sgt != NULL, ("%s: S/G table is NULL", __func__)); /* @@ -3371,102 +3385,6 @@ dpaa2_ni_cmp_api_version(struct dpaa2_ni_softc *sc, uint16_t major, return sc->api_major - major; } -/** - * @brief Build a DPAA2 frame descriptor. - */ -static int -dpaa2_ni_build_fd(struct dpaa2_ni_softc *sc, struct dpaa2_ni_tx_ring *tx, - struct dpaa2_buf *buf, bus_dma_segment_t *segs, int nsegs, struct dpaa2_fd *fd) -{ - struct dpaa2_buf *sgt = buf->sgt; - struct dpaa2_sg_entry *sge; - struct dpaa2_fa *fa; - int i, error; - - KASSERT(nsegs <= DPAA2_TX_SEGLIMIT, ("%s: too many segments", __func__)); - KASSERT(buf->opt != NULL, ("%s: no Tx ring?", __func__)); - KASSERT(sgt != NULL, ("%s: no S/G table?", __func__)); - KASSERT(sgt->vaddr != NULL, ("%s: no S/G vaddr?", __func__)); - - memset(fd, 0, sizeof(*fd)); - - /* Populate and map S/G table */ - if (__predict_true(nsegs <= DPAA2_TX_SEGLIMIT)) { - sge = (struct dpaa2_sg_entry *)sgt->vaddr + sc->tx_data_off; - for (i = 0; i < nsegs; i++) { - sge[i].addr = (uint64_t)segs[i].ds_addr; - sge[i].len = (uint32_t)segs[i].ds_len; - sge[i].offset_fmt = 0u; - } - sge[i-1].offset_fmt |= 0x8000u; /* set final entry flag */ - - KASSERT(sgt->paddr == 0, ("%s: paddr(%#jx) != 0", __func__, - sgt->paddr)); - - error = bus_dmamap_load(sgt->dmat, sgt->dmap, sgt->vaddr, - DPAA2_TX_SGT_SZ, dpaa2_dmamap_oneseg_cb, &sgt->paddr, - BUS_DMA_NOWAIT); - if (__predict_false(error != 0)) { - device_printf(sc->dev, "%s: bus_dmamap_load() failed: " - "error=%d\n", __func__, error); - return (error); - } - - buf->paddr = sgt->paddr; - buf->vaddr = sgt->vaddr; - sc->tx_sg_frames++; /* for sysctl(9) */ - } else { - return (EINVAL); - } - - fa = (struct dpaa2_fa *)sgt->vaddr; - fa->magic = DPAA2_MAGIC; - fa->buf = buf; - - fd->addr = buf->paddr; - fd->data_length = (uint32_t)buf->m->m_pkthdr.len; - fd->bpid_ivp_bmt = 0; - fd->offset_fmt_sl = 0x2000u | sc->tx_data_off; - fd->ctrl = 0x00800000u; - - return (0); -} - -static int -dpaa2_ni_fd_err(struct dpaa2_fd *fd) -{ - return ((fd->ctrl >> DPAA2_NI_FD_ERR_SHIFT) & DPAA2_NI_FD_ERR_MASK); -} - -static uint32_t -dpaa2_ni_fd_data_len(struct dpaa2_fd *fd) -{ - if (dpaa2_ni_fd_short_len(fd)) { - return (fd->data_length & DPAA2_NI_FD_LEN_MASK); - } - return (fd->data_length); -} - -static int -dpaa2_ni_fd_format(struct dpaa2_fd *fd) -{ - return ((enum dpaa2_fd_format)((fd->offset_fmt_sl >> - DPAA2_NI_FD_FMT_SHIFT) & DPAA2_NI_FD_FMT_MASK)); -} - -static bool -dpaa2_ni_fd_short_len(struct dpaa2_fd *fd) -{ - return (((fd->offset_fmt_sl >> DPAA2_NI_FD_SL_SHIFT) - & DPAA2_NI_FD_SL_MASK) == 1); -} - -static int -dpaa2_ni_fd_offset(struct dpaa2_fd *fd) -{ - return (fd->offset_fmt_sl & DPAA2_NI_FD_OFFSET_MASK); -} - /** * @brief Collect statistics of the network interface. */ diff --git a/sys/dev/dpaa2/dpaa2_ni.h b/sys/dev/dpaa2/dpaa2_ni.h index 6fb0673fac09..fcd37501ebd0 100644 --- a/sys/dev/dpaa2/dpaa2_ni.h +++ b/sys/dev/dpaa2/dpaa2_ni.h @@ -490,8 +490,9 @@ struct dpaa2_ni_softc { struct dpaa2_channel *channels[DPAA2_MAX_CHANNELS]; struct dpaa2_ni_fq rxe_queue; /* one per DPNI */ + /* sysctl(9) */ struct dpaa2_atomic buf_num; - struct dpaa2_atomic buf_free; /* for sysctl(9) only */ + struct dpaa2_atomic buf_free; int irq_rid[DPAA2_NI_MSI_COUNT]; struct resource *irq_res; diff --git a/sys/dev/dpaa2/dpaa2_swp.h b/sys/dev/dpaa2/dpaa2_swp.h index 1b1383b4241f..20980c6b71b7 100644 --- a/sys/dev/dpaa2/dpaa2_swp.h +++ b/sys/dev/dpaa2/dpaa2_swp.h @@ -35,6 +35,7 @@ #include "dpaa2_types.h" #include "dpaa2_buf.h" #include "dpaa2_bp.h" +#include "dpaa2_frame.h" /* * DPAA2 QBMan software portal. @@ -200,10 +201,8 @@ #define DPAA2_EQ_DESC_SIZE 32u /* Enqueue Command Descriptor */ #define DPAA2_FDR_DESC_SIZE 32u /* Descriptor of the FDR */ -#define DPAA2_FD_SIZE 32u /* Frame Descriptor */ #define DPAA2_FDR_SIZE 64u /* Frame Dequeue Response */ #define DPAA2_SCN_SIZE 16u /* State Change Notification */ -#define DPAA2_FA_SIZE 64u /* SW Frame Annotation */ #define DPAA2_SGE_SIZE 16u /* S/G table entry */ #define DPAA2_DQ_SIZE 64u /* Dequeue Response */ #define DPAA2_SWP_CMD_SIZE 64u /* SWP Command */ @@ -284,54 +283,6 @@ struct dpaa2_scn { } __packed; CTASSERT(sizeof(struct dpaa2_scn) == DPAA2_SCN_SIZE); -/** - * @brief DPAA2 frame descriptor. - * - * addr: Memory address of the start of the buffer holding the - * frame data or the buffer containing the scatter/gather - * list. - * data_length: Length of the frame data (in bytes). - * bpid_ivp_bmt: Buffer pool ID (14 bit + BMT bit + IVP bit) - * offset_fmt_sl: Frame data offset, frame format and short-length fields. - * frame_ctx: Frame context. This field allows the sender of a frame - * to communicate some out-of-band information to the - * receiver of the frame. - * ctrl: Control bits (ERR, CBMT, ASAL, PTAC, DROPP, SC, DD). - * flow_ctx: Frame flow context. Associates the frame with a flow - * structure. QMan may use the FLC field for 3 purposes: - * stashing control, order definition point identification, - * and enqueue replication control. - */ -struct dpaa2_fd { - uint64_t addr; - uint32_t data_length; - uint16_t bpid_ivp_bmt; - uint16_t offset_fmt_sl; - uint32_t frame_ctx; - uint32_t ctrl; - uint64_t flow_ctx; -} __packed; -CTASSERT(sizeof(struct dpaa2_fd) == DPAA2_FD_SIZE); - -/** - * @brief DPAA2 frame annotation. - */ -struct dpaa2_fa { - uint32_t magic; - struct dpaa2_buf *buf; -#ifdef __notyet__ - union { - struct { /* Tx frame annotation */ - struct dpaa2_ni_tx_ring *tx; - }; - struct { /* Rx frame annotation */ - uint64_t _notused; - }; - }; -#endif -} __packed; -CTASSERT(sizeof(struct dpaa2_fa) <= DPAA2_FA_SIZE); - /** * @brief DPAA2 scatter/gather entry. */ diff --git a/sys/dev/dpaa2/dpaa2_types.h b/sys/dev/dpaa2/dpaa2_types.h index dbfac9ce0a40..dc1c232c09c2 100644 --- a/sys/dev/dpaa2/dpaa2_types.h +++ b/sys/dev/dpaa2/dpaa2_types.h @@ -40,6 +40,11 @@ #define DPAA2_MAX_CHANNELS 16 /* CPU cores */ #define DPAA2_MAX_TCS 8 /* Traffic classes */ +#define DPAA2_TX_SEGLIMIT (16u) /* for 64 KiB frames */ +#define DPAA2_TX_SEG_SZ (PAGE_SIZE) +#define DPAA2_TX_SEGS_MAXSZ (DPAA2_TX_SEGLIMIT * DPAA2_TX_SEG_SZ) +#define DPAA2_TX_SGT_SZ (PAGE_SIZE) /* in bytes */ + /** * @brief Types of the DPAA2 devices. */ diff --git a/sys/modules/dpaa2/Makefile b/sys/modules/dpaa2/Makefile index 816d6fa5cf4a..388303eed0c7 100644 --- a/sys/modules/dpaa2/Makefile +++ b/sys/modules/dpaa2/Makefile @@ -14,6 +14,7 @@ SRCS+= dpaa2_con.c SRCS+= dpaa2_buf.c SRCS+= dpaa2_channel.c SRCS+= dpaa2_types.c +SRCS+= dpaa2_frame.c SRCS+= dpaa2_cmd_if.c dpaa2_cmd_if.h SRCS+= dpaa2_swp_if.c dpaa2_swp_if.h
