The branch main has been updated by br:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=974ecf68903d3887324f534a3bca21f1ae501819

commit 974ecf68903d3887324f534a3bca21f1ae501819
Author:     Ruslan Bukin <[email protected]>
AuthorDate: 2025-11-26 16:26:31 +0000
Commit:     Ruslan Bukin <[email protected]>
CommitDate: 2025-11-26 16:38:07 +0000

    xae(4), axidma(4): rewrite DMA operation.
    
    Due to performance constraints on a synthesized CHERI RISC-V core,
    remove usage of xdma(4) scatter-gather framework.  Instead, provide
    a minimalistic interface between two drivers.
    
    This increases performance ~4-5 times.
    Tested using scp(1) and nc(1) on Codasip Prime.
    
    Sponsored by:   CHERI Research Centre
    Differential Revision:  https://reviews.freebsd.org/D53932
---
 sys/conf/files.riscv       |   3 +-
 sys/dev/xilinx/axidma.c    | 528 ++----------------------
 sys/dev/xilinx/axidma.h    |  11 +-
 sys/dev/xilinx/axidma_if.m |  53 +++
 sys/dev/xilinx/if_xae.c    | 997 +++++++++++++++++++++++++++------------------
 sys/dev/xilinx/if_xaevar.h |  51 ++-
 6 files changed, 747 insertions(+), 896 deletions(-)

diff --git a/sys/conf/files.riscv b/sys/conf/files.riscv
index e77a15ce8dae..2a80064e88ba 100644
--- a/sys/conf/files.riscv
+++ b/sys/conf/files.riscv
@@ -23,7 +23,8 @@ dev/vmm/vmm_dev.c             optional        vmm
 dev/vmm/vmm_mem.c              optional        vmm
 dev/vmm/vmm_stat.c             optional        vmm
 dev/xilinx/axi_quad_spi.c      optional        xilinx_spi
-dev/xilinx/axidma.c            optional        axidma xdma
+dev/xilinx/axidma.c            optional        axidma
+dev/xilinx/axidma_if.m         optional        axidma
 dev/xilinx/if_xae.c            optional        xae
 dev/xilinx/xlnx_pcib.c         optional        pci fdt xlnx_pcib
 kern/msi_if.m                  standard
diff --git a/sys/dev/xilinx/axidma.c b/sys/dev/xilinx/axidma.c
index 77a46c712980..29757a335dee 100644
--- a/sys/dev/xilinx/axidma.c
+++ b/sys/dev/xilinx/axidma.c
@@ -1,7 +1,7 @@
 /*-
  * SPDX-License-Identifier: BSD-2-Clause
  *
- * Copyright (c) 2019 Ruslan Bukin <[email protected]>
+ * Copyright (c) 2019-2025 Ruslan Bukin <[email protected]>
  *
  * This software was developed by SRI International and the University of
  * Cambridge Computer Laboratory (Department of Computer Science and
@@ -30,13 +30,11 @@
  * SUCH DAMAGE.
  */
 
-/* Xilinx AXI DMA controller driver. */
+/*
+ * Xilinx AXI Ethernet DMA controller driver.
+ */
 
-#include <sys/cdefs.h>
-#include "opt_platform.h"
-#include <sys/param.h>
 #include <sys/systm.h>
-#include <sys/conf.h>
 #include <sys/bus.h>
 #include <sys/kernel.h>
 #include <sys/module.h>
@@ -44,67 +42,32 @@
 
 #include <machine/bus.h>
 
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_page.h>
-
-#ifdef FDT
-#include <dev/fdt/fdt_common.h>
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
-#endif
 
-#include <dev/xdma/xdma.h>
 #include <dev/xilinx/axidma.h>
 
-#include "xdma_if.h"
+#include "axidma_if.h"
 
-#define        READ4(_sc, _reg)        \
+#define        AXIDMA_RD4(_sc, _reg)   \
        bus_space_read_4(_sc->bst, _sc->bsh, _reg)
-#define        WRITE4(_sc, _reg, _val) \
+#define        AXIDMA_WR4(_sc, _reg, _val)     \
        bus_space_write_4(_sc->bst, _sc->bsh, _reg, _val)
-#define        READ8(_sc, _reg)        \
+#define        AXIDMA_RD8(_sc, _reg)   \
        bus_space_read_8(_sc->bst, _sc->bsh, _reg)
-#define        WRITE8(_sc, _reg, _val) \
+#define        AXIDMA_WR8(_sc, _reg, _val)     \
        bus_space_write_8(_sc->bst, _sc->bsh, _reg, _val)
 
-#define AXIDMA_DEBUG
-#undef AXIDMA_DEBUG
-
-#ifdef AXIDMA_DEBUG
-#define dprintf(fmt, ...)  printf(fmt, ##__VA_ARGS__)
-#else
-#define dprintf(fmt, ...)
-#endif
-
-extern struct bus_space memmap_bus;
-
-struct axidma_channel {
-       struct axidma_softc     *sc;
-       xdma_channel_t          *xchan;
-       bool                    used;
-       int                     idx_head;
-       int                     idx_tail;
-
-       struct axidma_desc      **descs;
-       vm_paddr_t              *descs_phys;
-       uint32_t                descs_num;
+#define        dprintf(fmt, ...)
 
-       vm_size_t               mem_size;
-       vm_offset_t             mem_paddr;
-       vm_offset_t             mem_vaddr;
-
-       uint32_t                descs_used_count;
-};
+#define        AXIDMA_MAX_CHANNELS     2
 
 struct axidma_softc {
        device_t                dev;
-       struct resource         *res[3];
+       struct resource         *res[1 + AXIDMA_MAX_CHANNELS];
        bus_space_tag_t         bst;
        bus_space_handle_t      bsh;
-       void                    *ih[2];
-       struct axidma_desc      desc;
-       struct axidma_channel   channels[AXIDMA_NCHANNELS];
+       void                    *ih[AXIDMA_MAX_CHANNELS];
 };
 
 static struct resource_spec axidma_spec[] = {
@@ -114,144 +77,19 @@ static struct resource_spec axidma_spec[] = {
        { -1, 0 }
 };
 
-#define        HWTYPE_NONE     0
-#define        HWTYPE_STD      1
-
 static struct ofw_compat_data compat_data[] = {
-       { "xlnx,eth-dma",       HWTYPE_STD },
-       { NULL,                 HWTYPE_NONE },
+       { "xlnx,eth-dma",       1 },
+       { NULL,                 0 },
 };
 
-static int axidma_probe(device_t dev);
-static int axidma_attach(device_t dev);
-static int axidma_detach(device_t dev);
-
-static inline uint32_t
-axidma_next_desc(struct axidma_channel *chan, uint32_t curidx)
-{
-
-       return ((curidx + 1) % chan->descs_num);
-}
-
-static void
-axidma_intr(struct axidma_softc *sc,
-    struct axidma_channel *chan)
-{
-       xdma_transfer_status_t status;
-       xdma_transfer_status_t st;
-       struct axidma_fdt_data *data;
-       xdma_controller_t *xdma;
-       struct axidma_desc *desc;
-       struct xdma_channel *xchan;
-       uint32_t tot_copied;
-       int pending;
-       int errors;
-
-       xchan = chan->xchan;
-       xdma = xchan->xdma;
-       data = xdma->data;
-
-       pending = READ4(sc, AXI_DMASR(data->id));
-       WRITE4(sc, AXI_DMASR(data->id), pending);
-
-       errors = (pending & (DMASR_DMAINTERR | DMASR_DMASLVERR
-                       | DMASR_DMADECOREERR | DMASR_SGINTERR
-                       | DMASR_SGSLVERR | DMASR_SGDECERR));
-
-       dprintf("%s: AXI_DMASR %x\n", __func__,
-           READ4(sc, AXI_DMASR(data->id)));
-       dprintf("%s: AXI_CURDESC %x\n", __func__,
-           READ4(sc, AXI_CURDESC(data->id)));
-       dprintf("%s: AXI_TAILDESC %x\n", __func__,
-           READ4(sc, AXI_TAILDESC(data->id)));
-
-       tot_copied = 0;
-
-       while (chan->idx_tail != chan->idx_head) {
-               desc = chan->descs[chan->idx_tail];
-               cpu_dcache_wbinv_range((vm_offset_t)desc,
-                   sizeof(struct axidma_desc));
-
-               if ((desc->status & BD_STATUS_CMPLT) == 0)
-                       break;
-
-               st.error = errors;
-               st.transferred = desc->status & BD_CONTROL_LEN_M;
-               tot_copied += st.transferred;
-               xchan_seg_done(xchan, &st);
-
-               chan->idx_tail = axidma_next_desc(chan, chan->idx_tail);
-               atomic_subtract_int(&chan->descs_used_count, 1);
-       }
-
-       /* Finish operation */
-       status.error = errors;
-       status.transferred = tot_copied;
-       xdma_callback(chan->xchan, &status);
-}
-
-static void
-axidma_intr_rx(void *arg)
-{
-       struct axidma_softc *sc;
-       struct axidma_channel *chan;
-
-       dprintf("%s\n", __func__);
-
-       sc = arg;
-       chan = &sc->channels[AXIDMA_RX_CHAN];
-
-       axidma_intr(sc, chan);
-}
-
-static void
-axidma_intr_tx(void *arg)
-{
-       struct axidma_softc *sc;
-       struct axidma_channel *chan;
-
-       dprintf("%s\n", __func__);
-
-       sc = arg;
-       chan = &sc->channels[AXIDMA_TX_CHAN];
-
-       axidma_intr(sc, chan);
-}
-
-static int
-axidma_reset(struct axidma_softc *sc, int chan_id)
-{
-       int timeout;
-
-       WRITE4(sc, AXI_DMACR(chan_id), DMACR_RESET);
-
-       timeout = 100;
-       do {
-               if ((READ4(sc, AXI_DMACR(chan_id)) & DMACR_RESET) == 0)
-                       break;
-       } while (timeout--);
-
-       dprintf("timeout %d\n", timeout);
-
-       if (timeout == 0)
-               return (-1);
-
-       dprintf("%s: read control after reset: %x\n",
-           __func__, READ4(sc, AXI_DMACR(chan_id)));
-
-       return (0);
-}
-
 static int
 axidma_probe(device_t dev)
 {
-       int hwtype;
 
        if (!ofw_bus_status_okay(dev))
                return (ENXIO);
 
-       hwtype = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
-       if (hwtype == HWTYPE_NONE)
+       if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
                return (ENXIO);
 
        device_set_desc(dev, "Xilinx AXI DMA");
@@ -264,7 +102,6 @@ axidma_attach(device_t dev)
 {
        struct axidma_softc *sc;
        phandle_t xref, node;
-       int err;
 
        sc = device_get_softc(dev);
        sc->dev = dev;
@@ -278,22 +115,6 @@ axidma_attach(device_t dev)
        sc->bst = rman_get_bustag(sc->res[0]);
        sc->bsh = rman_get_bushandle(sc->res[0]);
 
-       /* Setup interrupt handler */
-       err = bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC | INTR_MPSAFE,
-           NULL, axidma_intr_tx, sc, &sc->ih[0]);
-       if (err) {
-               device_printf(dev, "Unable to alloc interrupt resource.\n");
-               return (ENXIO);
-       }
-
-       /* Setup interrupt handler */
-       err = bus_setup_intr(dev, sc->res[2], INTR_TYPE_MISC | INTR_MPSAFE,
-           NULL, axidma_intr_rx, sc, &sc->ih[1]);
-       if (err) {
-               device_printf(dev, "Unable to alloc interrupt resource.\n");
-               return (ENXIO);
-       }
-
        node = ofw_bus_get_node(dev);
        xref = OF_xref_from_node(node);
        OF_device_register_xref(xref, dev);
@@ -302,331 +123,72 @@ axidma_attach(device_t dev)
 }
 
 static int
-axidma_detach(device_t dev)
+axidma_reset(device_t dev, int chan_id)
 {
        struct axidma_softc *sc;
+       int timeout;
 
        sc = device_get_softc(dev);
 
-       bus_teardown_intr(dev, sc->res[1], sc->ih[0]);
-       bus_teardown_intr(dev, sc->res[2], sc->ih[1]);
-       bus_release_resources(dev, axidma_spec, sc->res);
-
-       return (0);
-}
-
-static int
-axidma_desc_free(struct axidma_softc *sc, struct axidma_channel *chan)
-{
-       struct xdma_channel *xchan;
-
-       xchan = chan->xchan;
-
-       free(chan->descs, M_DEVBUF);
-       free(chan->descs_phys, M_DEVBUF);
-
-       pmap_kremove_device(chan->mem_vaddr, chan->mem_size);
-       kva_free(chan->mem_vaddr, chan->mem_size);
-       vmem_free(xchan->vmem, chan->mem_paddr, chan->mem_size);
-
-       return (0);
-}
-
-static int
-axidma_desc_alloc(struct axidma_softc *sc, struct xdma_channel *xchan,
-    uint32_t desc_size)
-{
-       struct axidma_channel *chan;
-       int nsegments;
-       int i;
-
-       chan = (struct axidma_channel *)xchan->chan;
-       nsegments = chan->descs_num;
-
-       chan->descs = malloc(nsegments * sizeof(struct axidma_desc *),
-           M_DEVBUF, M_NOWAIT | M_ZERO);
-       if (chan->descs == NULL) {
-               device_printf(sc->dev,
-                   "%s: Can't allocate memory.\n", __func__);
-               return (-1);
-       }
-
-       chan->descs_phys = malloc(nsegments * sizeof(bus_dma_segment_t),
-           M_DEVBUF, M_NOWAIT | M_ZERO);
-       chan->mem_size = desc_size * nsegments;
-       if (vmem_alloc(xchan->vmem, chan->mem_size, M_FIRSTFIT | M_NOWAIT,
-           &chan->mem_paddr)) {
-               device_printf(sc->dev, "Failed to allocate memory.\n");
-               return (-1);
-       }
-       chan->mem_vaddr = kva_alloc(chan->mem_size);
-       pmap_kenter(chan->mem_vaddr, chan->mem_size, chan->mem_paddr,
-           VM_MEMATTR_DEFAULT);
-
-       device_printf(sc->dev, "Allocated chunk %lx %lu\n",
-           chan->mem_paddr, chan->mem_size);
-
-       for (i = 0; i < nsegments; i++) {
-               chan->descs[i] = (struct axidma_desc *)
-                   ((uint64_t)chan->mem_vaddr + desc_size * i);
-               chan->descs_phys[i] = chan->mem_paddr + desc_size * i;
-       }
+       AXIDMA_WR4(sc, AXI_DMACR(chan_id), DMACR_RESET);
 
-       return (0);
-}
+       timeout = 100;
 
-static int
-axidma_channel_alloc(device_t dev, struct xdma_channel *xchan)
-{
-       xdma_controller_t *xdma;
-       struct axidma_fdt_data *data;
-       struct axidma_channel *chan;
-       struct axidma_softc *sc;
+       do {
+               if ((AXIDMA_RD4(sc, AXI_DMACR(chan_id)) & DMACR_RESET) == 0)
+                       break;
+       } while (timeout--);
 
-       sc = device_get_softc(dev);
+       dprintf("timeout %d\n", timeout);
 
-       if (xchan->caps & XCHAN_CAP_BUSDMA) {
-               device_printf(sc->dev,
-                   "Error: busdma operation is not implemented.");
+       if (timeout == 0)
                return (-1);
-       }
 
-       xdma = xchan->xdma;
-       data = xdma->data;
-
-       chan = &sc->channels[data->id];
-       if (chan->used == false) {
-               if (axidma_reset(sc, data->id) != 0)
-                       return (-1);
-               chan->xchan = xchan;
-               xchan->caps |= XCHAN_CAP_BOUNCE;
-               xchan->chan = (void *)chan;
-               chan->sc = sc;
-               chan->used = true;
-               chan->idx_head = 0;
-               chan->idx_tail = 0;
-               chan->descs_used_count = 0;
-               chan->descs_num = AXIDMA_DESCS_NUM;
-
-               return (0);
-       }
-
-       return (-1);
-}
-
-static int
-axidma_channel_free(device_t dev, struct xdma_channel *xchan)
-{
-       struct axidma_channel *chan;
-       struct axidma_softc *sc;
-
-       sc = device_get_softc(dev);
-
-       chan = (struct axidma_channel *)xchan->chan;
-
-       axidma_desc_free(sc, chan);
-
-       chan->used = false;
-
-       return (0);
-}
-
-static int
-axidma_channel_capacity(device_t dev, xdma_channel_t *xchan,
-    uint32_t *capacity)
-{
-       struct axidma_channel *chan;
-       uint32_t c;
-
-       chan = (struct axidma_channel *)xchan->chan;
-
-       /* At least one descriptor must be left empty. */
-       c = (chan->descs_num - chan->descs_used_count - 1);
-
-       *capacity = c;
+       dprintf("%s: read control after reset: %x\n",
+           __func__, AXIDMA_RD4(sc, AXI_DMACR(chan_id)));
 
        return (0);
 }
 
-static int
-axidma_channel_submit_sg(device_t dev, struct xdma_channel *xchan,
-    struct xdma_sglist *sg, uint32_t sg_n)
+static struct resource *
+axidma_memres(device_t dev)
 {
-       xdma_controller_t *xdma;
-       struct axidma_fdt_data *data;
-       struct axidma_channel *chan;
-       struct axidma_desc *desc;
        struct axidma_softc *sc;
-       uint32_t src_addr;
-       uint32_t dst_addr;
-       uint32_t addr;
-       uint32_t len;
-       uint32_t tmp;
-       int i;
-
-       dprintf("%s: sg_n %d\n", __func__, sg_n);
 
        sc = device_get_softc(dev);
 
-       chan = (struct axidma_channel *)xchan->chan;
-       xdma = xchan->xdma;
-       data = xdma->data;
-
-       if (sg_n == 0)
-               return (0);
-
-       tmp = 0;
-
-       for (i = 0; i < sg_n; i++) {
-               src_addr = (uint32_t)sg[i].src_addr;
-               dst_addr = (uint32_t)sg[i].dst_addr;
-               len = (uint32_t)sg[i].len;
-
-               dprintf("%s(%d): src %x dst %x len %d\n", __func__,
-                   data->id, src_addr, dst_addr, len);
-
-               desc = chan->descs[chan->idx_head];
-               if (sg[i].direction == XDMA_MEM_TO_DEV)
-                       desc->phys = src_addr;
-               else
-                       desc->phys = dst_addr;
-               desc->status = 0;
-               desc->control = len;
-               if (sg[i].first == 1)
-                       desc->control |= BD_CONTROL_TXSOF;
-               if (sg[i].last == 1)
-                       desc->control |= BD_CONTROL_TXEOF;
-
-               cpu_dcache_wbinv_range((vm_offset_t)desc,
-                   sizeof(struct axidma_desc));
-
-               tmp = chan->idx_head;
-
-               atomic_add_int(&chan->descs_used_count, 1);
-               chan->idx_head = axidma_next_desc(chan, chan->idx_head);
-       }
-
-       dprintf("%s(%d): _curdesc %x\n", __func__, data->id,
-           READ8(sc, AXI_CURDESC(data->id)));
-       dprintf("%s(%d): _curdesc %x\n", __func__, data->id,
-           READ8(sc, AXI_CURDESC(data->id)));
-       dprintf("%s(%d): status %x\n", __func__, data->id,
-           READ4(sc, AXI_DMASR(data->id)));
-
-       addr = chan->descs_phys[tmp];
-       WRITE8(sc, AXI_TAILDESC(data->id), addr);
-
-       return (0);
+       return (sc->res[0]);
 }
 
 static int
-axidma_channel_prep_sg(device_t dev, struct xdma_channel *xchan)
+axidma_setup_cb(device_t dev, int chan_id, void (*cb)(void *), void *arg)
 {
-       xdma_controller_t *xdma;
-       struct axidma_fdt_data *data;
-       struct axidma_channel *chan;
-       struct axidma_desc *desc;
        struct axidma_softc *sc;
-       uint32_t addr;
-       uint32_t reg;
-       int ret;
-       int i;
+       int error;
 
        sc = device_get_softc(dev);
 
-       chan = (struct axidma_channel *)xchan->chan;
-       xdma = xchan->xdma;
-       data = xdma->data;
-
-       dprintf("%s(%d)\n", __func__, data->id);
-
-       ret = axidma_desc_alloc(sc, xchan, sizeof(struct axidma_desc));
-       if (ret != 0) {
-               device_printf(sc->dev,
-                   "%s: Can't allocate descriptors.\n", __func__);
-               return (-1);
-       }
-
-       for (i = 0; i < chan->descs_num; i++) {
-               desc = chan->descs[i];
-               bzero(desc, sizeof(struct axidma_desc));
-
-               if (i == (chan->descs_num - 1))
-                       desc->next = chan->descs_phys[0];
-               else
-                       desc->next = chan->descs_phys[i + 1];
-               desc->status = 0;
-               desc->control = 0;
-
-               dprintf("%s(%d): desc %d vaddr %lx next paddr %x\n", __func__,
-                   data->id, i, (uint64_t)desc, le32toh(desc->next));
-       }
-
-       addr = chan->descs_phys[0];
-       WRITE8(sc, AXI_CURDESC(data->id), addr);
-
-       reg = READ4(sc, AXI_DMACR(data->id));
-       reg |= DMACR_IOC_IRQEN | DMACR_DLY_IRQEN | DMACR_ERR_IRQEN;
-       WRITE4(sc, AXI_DMACR(data->id), reg);
-       reg |= DMACR_RS;
-       WRITE4(sc, AXI_DMACR(data->id), reg);
-
-       return (0);
-}
-
-static int
-axidma_channel_control(device_t dev, xdma_channel_t *xchan, int cmd)
-{
-
-       switch (cmd) {
-       case XDMA_CMD_BEGIN:
-       case XDMA_CMD_TERMINATE:
-       case XDMA_CMD_PAUSE:
-               /* TODO: implement me */
-               return (-1);
-       }
-
-       return (0);
-}
+       if (sc->ih[chan_id] != NULL)
+               return (EEXIST);
 
-#ifdef FDT
-static int
-axidma_ofw_md_data(device_t dev, pcell_t *cells, int ncells, void **ptr)
-{
-       struct axidma_fdt_data *data;
-
-       if (ncells != 1)
-               return (-1);
-
-       data = malloc(sizeof(struct axidma_fdt_data),
-           M_DEVBUF, (M_WAITOK | M_ZERO));
-       data->id = cells[0];
-
-       *ptr = data;
+       error = bus_setup_intr(dev, sc->res[chan_id + 1],
+           INTR_TYPE_MISC | INTR_MPSAFE, NULL, cb, arg,
+           &sc->ih[chan_id]);
+       if (error)
+               device_printf(dev, "Unable to alloc interrupt resource.\n");
 
-       return (0);
+       return (error);
 }
-#endif
 
 static device_method_t axidma_methods[] = {
        /* Device interface */
        DEVMETHOD(device_probe,                 axidma_probe),
        DEVMETHOD(device_attach,                axidma_attach),
-       DEVMETHOD(device_detach,                axidma_detach),
-
-       /* xDMA Interface */
-       DEVMETHOD(xdma_channel_alloc,           axidma_channel_alloc),
-       DEVMETHOD(xdma_channel_free,            axidma_channel_free),
-       DEVMETHOD(xdma_channel_control,         axidma_channel_control),
-
-       /* xDMA SG Interface */
-       DEVMETHOD(xdma_channel_capacity,        axidma_channel_capacity),
-       DEVMETHOD(xdma_channel_prep_sg,         axidma_channel_prep_sg),
-       DEVMETHOD(xdma_channel_submit_sg,       axidma_channel_submit_sg),
 
-#ifdef FDT
-       DEVMETHOD(xdma_ofw_md_data,             axidma_ofw_md_data),
-#endif
+       /* Axidma interface */
+       DEVMETHOD(axidma_reset,                 axidma_reset),
+       DEVMETHOD(axidma_memres,                axidma_memres),
+       DEVMETHOD(axidma_setup_cb,              axidma_setup_cb),
 
        DEVMETHOD_END
 };
diff --git a/sys/dev/xilinx/axidma.h b/sys/dev/xilinx/axidma.h
index a6834354fafc..f655d5d70ede 100644
--- a/sys/dev/xilinx/axidma.h
+++ b/sys/dev/xilinx/axidma.h
@@ -1,7 +1,7 @@
 /*-
  * SPDX-License-Identifier: BSD-2-Clause
  *
- * Copyright (c) 2019 Ruslan Bukin <[email protected]>
+ * Copyright (c) 2019-2025 Ruslan Bukin <[email protected]>
  *
  * This software was developed by SRI International and the University of
  * Cambridge Computer Laboratory (Department of Computer Science and
@@ -58,11 +58,6 @@
 #define        AXI_TAILDESC_MSB(n)     (0x14 + 0x30 * (n)) /* Tail Descriptor 
Pointer. Upper 32 bits of address. */
 #define        AXI_SG_CTL              0x2C /* Scatter/Gather User and Cache */
 
-#define        AXIDMA_NCHANNELS        2
-#define        AXIDMA_DESCS_NUM        512
-#define        AXIDMA_TX_CHAN          0
-#define        AXIDMA_RX_CHAN          1
-
 struct axidma_desc {
        uint32_t next;
        uint32_t reserved1;
@@ -87,8 +82,4 @@ struct axidma_desc {
        uint32_t reserved[3];
 };
 
-struct axidma_fdt_data {
-       int id;
-};
-
 #endif /* !_DEV_XILINX_AXIDMA_H_ */
diff --git a/sys/dev/xilinx/axidma_if.m b/sys/dev/xilinx/axidma_if.m
new file mode 100644
index 000000000000..ac6f4882c005
--- /dev/null
+++ b/sys/dev/xilinx/axidma_if.m
@@ -0,0 +1,53 @@
+#-
+# Copyright (c) 2025 Ruslan Bukin <[email protected]>
+#
+# This software was developed by SRI International and the University of
+# Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
+# ("CTSRD"), as part of the DARPA CRASH research programme.
+#
+# 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 <machine/bus.h>
+
+INTERFACE axidma;
+
+HEADER {
+       typedef void (*axidma_cb_t)(void *arg);
+};
+
+METHOD int reset {
+       device_t                dev;
+       int                     chan_id;
+};
+
+METHOD struct resource * memres {
+       device_t                dev;
+};
+
+METHOD int setup_cb {
+       device_t                dev;
+       int                     chan_id;
+       axidma_cb_t             cb;
+       void                    *arg;
+};
diff --git a/sys/dev/xilinx/if_xae.c b/sys/dev/xilinx/if_xae.c
index 97e7aa16dda4..7880f93c48ee 100644
--- a/sys/dev/xilinx/if_xae.c
+++ b/sys/dev/xilinx/if_xae.c
@@ -61,53 +61,38 @@
 #include <dev/mii/tiphy.h>
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
-#include <dev/xilinx/if_xaereg.h>
-#include <dev/xilinx/if_xaevar.h>
 
 #include <dev/xilinx/axidma.h>
+#include <dev/xilinx/if_xaereg.h>
+#include <dev/xilinx/if_xaevar.h>
 
 #include "miibus_if.h"
+#include "axidma_if.h"
 
-#define        READ4(_sc, _reg) \
-       bus_read_4((_sc)->res[0], _reg)
-#define        WRITE4(_sc, _reg, _val) \
-       bus_write_4((_sc)->res[0], _reg, _val)
+#define        XAE_RD4(_sc, _reg)              bus_read_4((_sc)->res[0], _reg)
+#define        XAE_RD8(_sc, _reg)              bus_read_8((_sc)->res[0], _reg)
+#define        XAE_WR4(_sc, _reg, _val)        bus_write_4((_sc)->res[0], 
_reg, _val)
+#define        XAE_WR8(_sc, _reg, _val)        bus_write_8((_sc)->res[0], 
_reg, _val)
 
-#define        READ8(_sc, _reg) \
-       bus_read_8((_sc)->res[0], _reg)
-#define        WRITE8(_sc, _reg, _val) \
-       bus_write_8((_sc)->res[0], _reg, _val)
+#define        AXIDMA_RD4(_sc, _reg)           bus_read_4((_sc)->dma_res, _reg)
+#define        AXIDMA_RD8(_sc, _reg)           bus_read_8((_sc)->dma_res, _reg)
+#define        AXIDMA_WR4(_sc, _reg, _val)     bus_write_4((_sc)->dma_res, 
_reg, _val)
+#define        AXIDMA_WR8(_sc, _reg, _val)     bus_write_8((_sc)->dma_res, 
_reg, _val)
 
 #define        XAE_LOCK(sc)                    mtx_lock(&(sc)->mtx)
 #define        XAE_UNLOCK(sc)                  mtx_unlock(&(sc)->mtx)
 #define        XAE_ASSERT_LOCKED(sc)           mtx_assert(&(sc)->mtx, MA_OWNED)
 #define        XAE_ASSERT_UNLOCKED(sc)         mtx_assert(&(sc)->mtx, 
MA_NOTOWNED)
 
-#define XAE_DEBUG
-#undef XAE_DEBUG
+#define        dprintf(fmt, ...)
 
-#ifdef XAE_DEBUG
-#define dprintf(fmt, ...)  printf(fmt, ##__VA_ARGS__)
-#else
-#define dprintf(fmt, ...)
-#endif
-
-#define        RX_QUEUE_SIZE           64
-#define        TX_QUEUE_SIZE           64
-#define        NUM_RX_MBUF             16
-#define        BUFRING_SIZE            8192
 #define        MDIO_CLK_DIV_DEFAULT    29
-#define        BUF_NPAGES              512
-
-#define        PHY1_RD(sc, _r)         \
-       xae_miibus_read_reg(sc->dev, 1, _r)
-#define        PHY1_WR(sc, _r, _v)     \
-       xae_miibus_write_reg(sc->dev, 1, _r, _v)
 
-#define        PHY_RD(sc, _r)          \
-       xae_miibus_read_reg(sc->dev, sc->phy_addr, _r)
+#define        PHY1_RD(sc, _r)         xae_miibus_read_reg(sc->dev, 1, _r)
+#define        PHY1_WR(sc, _r, _v)     xae_miibus_write_reg(sc->dev, 1, _r, _v)
+#define        PHY_RD(sc, _r)          xae_miibus_read_reg(sc->dev, 
sc->phy_addr, _r)
 #define        PHY_WR(sc, _r, _v)      \
-       xae_miibus_write_reg(sc->dev, sc->phy_addr, _r, _v)
+    xae_miibus_write_reg(sc->dev, sc->phy_addr, _r, _v)
 
 /* Use this macro to access regs > 0x1f */
 #define WRITE_TI_EREG(sc, reg, data) {                                 \
@@ -122,220 +107,384 @@
 #define        DP83867_SGMIICTL1               0xD3 /* not documented register 
*/
 #define         SGMIICTL1_SGMII_6W             (1 << 14) /* no idea what it is 
*/
 
+#define        AXI_DESC_RING_ALIGN             64
+
+/*
+ * Driver data and defines.
+ */
+
 static struct resource_spec xae_spec[] = {
        { SYS_RES_MEMORY,       0,      RF_ACTIVE },
        { SYS_RES_IRQ,          0,      RF_ACTIVE },
        { -1, 0 }
 };
 
-static void xae_stop_locked(struct xae_softc *sc);
-static void xae_setup_rxfilter(struct xae_softc *sc);
+static inline uint32_t
+next_rxidx(struct xae_softc *sc, uint32_t curidx)
+{
+
+       return ((curidx == RX_DESC_COUNT - 1) ? 0 : curidx + 1);
+}
 
-static int
-xae_rx_enqueue(struct xae_softc *sc, uint32_t n)
+static inline uint32_t
+next_txidx(struct xae_softc *sc, uint32_t curidx)
 {
-       struct mbuf *m;
-       int i;
 
-       for (i = 0; i < n; i++) {
-               m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
-               if (m == NULL) {
-                       device_printf(sc->dev,
-                           "%s: Can't alloc rx mbuf\n", __func__);
-                       return (-1);
-               }
+       return ((curidx == TX_DESC_COUNT - 1) ? 0 : curidx + 1);
+}
 
-               m->m_pkthdr.len = m->m_len = m->m_ext.ext_size;
-               xdma_enqueue_mbuf(sc->xchan_rx, &m, 0, 4, 4, XDMA_DEV_TO_MEM);
-       }
+static void
+xae_get1paddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
 
-       return (0);
+       if (error != 0)
+               return;
+       *(bus_addr_t *)arg = segs[0].ds_addr;
 }
 
-static int
-xae_get_phyaddr(phandle_t node, int *phy_addr)
+inline static uint32_t
+xae_setup_txdesc(struct xae_softc *sc, int idx, bus_addr_t paddr, 
+    uint32_t len)
 {
-       phandle_t phy_node;
-       pcell_t phy_handle, phy_reg;
+       struct axidma_desc *desc;
+       uint32_t nidx;
+       uint32_t flags;
 
-       if (OF_getencprop(node, "phy-handle", (void *)&phy_handle,
-           sizeof(phy_handle)) <= 0)
-               return (ENXIO);
+       nidx = next_txidx(sc, idx);
 
-       phy_node = OF_node_from_xref(phy_handle);
+       desc = &sc->txdesc_ring[idx];
 
-       if (OF_getencprop(phy_node, "reg", (void *)&phy_reg,
-           sizeof(phy_reg)) <= 0)
-               return (ENXIO);
+       /* Addr/len 0 means we're clearing the descriptor after xmit done. */
+       if (paddr == 0 || len == 0) {
+               flags = 0;
+               --sc->txcount;
+       } else {
+               flags = BD_CONTROL_TXSOF | BD_CONTROL_TXEOF;
+               ++sc->txcount;
+       }
 
-       *phy_addr = phy_reg;
+       desc->next = sc->txdesc_ring_paddr + sizeof(struct axidma_desc) * nidx;
+       desc->phys = paddr;
+       desc->status = 0;
+       desc->control = len | flags;
 
-       return (0);
+       return (nidx);
 }
 
 static int
-xae_xdma_tx_intr(void *arg, xdma_transfer_status_t *status)
+xae_setup_txbuf(struct xae_softc *sc, int idx, struct mbuf **mp)
 {
-       xdma_transfer_status_t st;
-       struct xae_softc *sc;
-       if_t ifp;
+       struct bus_dma_segment seg;
        struct mbuf *m;
-       int err;
-
-       sc = arg;
-
-       XAE_LOCK(sc);
+       int error;
+       int nsegs;
 
-       ifp = sc->ifp;
+       dprintf("%s\n", __func__);
 
-       for (;;) {
-               err = xdma_dequeue_mbuf(sc->xchan_tx, &m, &st);
-               if (err != 0) {
-                       break;
-               }
+       if ((m = m_defrag(*mp, M_NOWAIT)) == NULL)
+               return (ENOMEM);
 
-               if (st.error != 0) {
-                       if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
-               }
*** 1204 LINES SKIPPED ***

Reply via email to