Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 26 Nov 2025 16:39:21 +0000
From:      Ruslan Bukin <br@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 974ecf68903d - main - xae(4), axidma(4): rewrite DMA operation.
Message-ID:  <69272d39.37fb0.199f11e8@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by br:

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

commit 974ecf68903d3887324f534a3bca21f1ae501819
Author:     Ruslan Bukin <br@FreeBSD.org>
AuthorDate: 2025-11-26 16:26:31 +0000
Commit:     Ruslan Bukin <br@FreeBSD.org>
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 <br@bsdpad.com>
+ * Copyright (c) 2019-2025 Ruslan Bukin <br@bsdpad.com>
  *
  * 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 <br@bsdpad.com>
+ * Copyright (c) 2019-2025 Ruslan Bukin <br@bsdpad.com>
  *
  * 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 <br@bsdpad.com>
+#
+# 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 ***


help

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69272d39.37fb0.199f11e8>