svn commit: r346896 - in head/sys/dev: altera/atse altera/softdma xdma

Ruslan Bukin br at FreeBSD.org
Mon Apr 29 16:27:17 UTC 2019


Author: br
Date: Mon Apr 29 16:27:15 2019
New Revision: 346896
URL: https://svnweb.freebsd.org/changeset/base/346896

Log:
  o Rewrite softdma_process_tx() of Altera SoftDMA engine driver
    so it does not require a bounce buffer. The only need for this was
    to align the buffer address. Implement unaligned access and we don't
    need to copy data twice.
  o Remove contigmalloc-based bounce buffer from xDMA code since it is
    not suitable for arbitrary memory provided by platform, which is
    sometimes a dedicated piece of memory that is not managed by OS at all.
  
  Sponsored by:	DARPA, AFRL

Modified:
  head/sys/dev/altera/atse/if_atse.c
  head/sys/dev/altera/softdma/softdma.c
  head/sys/dev/xdma/xdma.h
  head/sys/dev/xdma/xdma_mbuf.c
  head/sys/dev/xdma/xdma_sg.c

Modified: head/sys/dev/altera/atse/if_atse.c
==============================================================================
--- head/sys/dev/altera/atse/if_atse.c	Mon Apr 29 16:26:29 2019	(r346895)
+++ head/sys/dev/altera/atse/if_atse.c	Mon Apr 29 16:27:15 2019	(r346896)
@@ -1290,7 +1290,7 @@ atse_attach(device_t dev)
 	 * Chapter 15. On-Chip FIFO Memory Core.
 	 * Embedded Peripherals IP User Guide.
 	 */
-	caps = XCHAN_CAP_BUSDMA_NOSEG;
+	caps = XCHAN_CAP_NOSEG;
 
 	/* Alloc xDMA virtual channel. */
 	sc->xchan_tx = xdma_channel_alloc(sc->xdma_tx, caps);
@@ -1456,6 +1456,11 @@ atse_detach(device_t dev)
 	}
 
 	mtx_destroy(&sc->atse_mtx);
+
+	xdma_channel_free(sc->xchan_tx);
+	xdma_channel_free(sc->xchan_rx);
+	xdma_put(sc->xdma_tx);
+	xdma_put(sc->xdma_rx);
 
 	return (0);
 }

Modified: head/sys/dev/altera/softdma/softdma.c
==============================================================================
--- head/sys/dev/altera/softdma/softdma.c	Mon Apr 29 16:26:29 2019	(r346895)
+++ head/sys/dev/altera/softdma/softdma.c	Mon Apr 29 16:27:15 2019	(r346896)
@@ -190,6 +190,18 @@ softdma_fill_level(struct softdma_softc *sc)
 	return (val);
 }
 
+static uint32_t
+fifo_fill_level_wait(struct softdma_softc *sc)
+{
+	uint32_t val;
+
+	do
+		val = softdma_fill_level(sc);
+	while (val == AVALON_FIFO_TX_BASIC_OPTS_DEPTH);
+
+	return (val);
+}
+
 static void
 softdma_intr(void *arg)
 {
@@ -287,86 +299,96 @@ static int
 softdma_process_tx(struct softdma_channel *chan, struct softdma_desc *desc)
 {
 	struct softdma_softc *sc;
-	uint32_t src_offs, dst_offs;
+	uint64_t addr;
+	uint64_t buf;
+	uint32_t word;
+	uint32_t missing;
 	uint32_t reg;
-	uint32_t fill_level;
-	uint32_t leftm;
-	uint32_t tmp;
-	uint32_t val;
-	uint32_t c;
+	int got_bits;
+	int len;
 
 	sc = chan->sc;
 
-	fill_level = softdma_fill_level(sc);
-	while (fill_level == AVALON_FIFO_TX_BASIC_OPTS_DEPTH)
-		fill_level = softdma_fill_level(sc);
+	fifo_fill_level_wait(sc);
 
 	/* Set start of packet. */
-	if (desc->control & CONTROL_GEN_SOP) {
-		reg = 0;
-		reg |= A_ONCHIP_FIFO_MEM_CORE_SOP;
-		softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA, reg);
-	}
+	if (desc->control & CONTROL_GEN_SOP)
+		softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA,
+		    A_ONCHIP_FIFO_MEM_CORE_SOP);
 
-	src_offs = dst_offs = 0;
-	c = 0;
-	while ((desc->len - c) >= 4) {
-		val = *(uint32_t *)(desc->src_addr + src_offs);
-		bus_write_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA, val);
-		if (desc->src_incr)
-			src_offs += 4;
-		if (desc->dst_incr)
-			dst_offs += 4;
-		fill_level += 1;
+	got_bits = 0;
+	buf = 0;
 
-		while (fill_level == AVALON_FIFO_TX_BASIC_OPTS_DEPTH) {
-			fill_level = softdma_fill_level(sc);
-		}
-		c += 4;
+	addr = desc->src_addr;
+	len = desc->len;
+
+	if (addr & 1) {
+		buf = (buf << 8) | *(uint8_t *)addr;
+		got_bits += 8;
+		addr += 1;
+		len -= 1;
 	}
 
-	val = 0;
-	leftm = (desc->len - c);
+	if (len >= 2 && addr & 2) {
+		buf = (buf << 16) | *(uint16_t *)addr;
+		got_bits += 16;
+		addr += 2;
+		len -= 2;
+	}
 
-	switch (leftm) {
-	case 1:
-		val = *(uint8_t *)(desc->src_addr + src_offs);
-		val <<= 24;
-		src_offs += 1;
-		break;
-	case 2:
-	case 3:
-		val = *(uint16_t *)(desc->src_addr + src_offs);
-		val <<= 16;
-		src_offs += 2;
+	while (len >= 4) {
+		buf = (buf << 32) | (uint64_t)*(uint32_t *)addr;
+		addr += 4;
+		len -= 4;
+		word = (uint32_t)((buf >> got_bits) & 0xffffffff);
 
-		if (leftm == 3) {
-			tmp = *(uint8_t *)(desc->src_addr + src_offs);
-			val |= (tmp << 8);
-			src_offs += 1;
-		}
-		break;
-	case 0:
-	default:
-		break;
+		fifo_fill_level_wait(sc);
+		if (len == 0 && got_bits == 0 &&
+		    (desc->control & CONTROL_GEN_EOP) != 0)
+			softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA,
+			    A_ONCHIP_FIFO_MEM_CORE_EOP);
+		bus_write_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA, word);
 	}
 
-	/* Set end of packet. */
-	reg = 0;
-	if (desc->control & CONTROL_GEN_EOP)
-		reg |= A_ONCHIP_FIFO_MEM_CORE_EOP;
-	reg |= ((4 - leftm) << A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT);
-	softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA, reg);
+	if (len & 2) {
+		buf = (buf << 16) | *(uint16_t *)addr;
+		got_bits += 16;
+		addr += 2;
+		len -= 2;
+	}
 
-	/* Ensure there is a FIFO entry available. */
-	fill_level = softdma_fill_level(sc);
-	while (fill_level == AVALON_FIFO_TX_BASIC_OPTS_DEPTH)
-		fill_level = softdma_fill_level(sc);
+	if (len & 1) {
+		buf = (buf << 8) | *(uint8_t *)addr;
+		got_bits += 8;
+		addr += 1;
+		len -= 1;
+	}
 
-	/* Final write */
-	bus_write_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA, val);
+	if (got_bits >= 32) {
+		got_bits -= 32;
+		word = (uint32_t)((buf >> got_bits) & 0xffffffff);
 
-	return (dst_offs);
+		fifo_fill_level_wait(sc);
+		if (len == 0 && got_bits == 0 &&
+		    (desc->control & CONTROL_GEN_EOP) != 0)
+			softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA,
+			    A_ONCHIP_FIFO_MEM_CORE_EOP);
+		bus_write_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA, word);
+	}
+
+	if (got_bits) {
+		missing = 32 - got_bits;
+		got_bits /= 8;
+
+		fifo_fill_level_wait(sc);
+		reg = A_ONCHIP_FIFO_MEM_CORE_EOP |
+		    ((4 - got_bits) << A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT);
+		softdma_mem_write(sc, A_ONCHIP_FIFO_MEM_CORE_METADATA, reg);
+		word = (uint32_t)((buf << missing) & 0xffffffff);
+		bus_write_4(sc->res[0], A_ONCHIP_FIFO_MEM_CORE_DATA, word);
+	}
+
+	return (desc->len);
 }
 
 static int
@@ -594,6 +616,8 @@ softdma_channel_alloc(device_t dev, struct xdma_channe
 		if (chan->used == 0) {
 			chan->xchan = xchan;
 			xchan->chan = (void *)chan;
+			xchan->caps |= XCHAN_CAP_NOBUFS;
+			xchan->caps |= XCHAN_CAP_NOSEG;
 			chan->index = i;
 			chan->idx_head = 0;
 			chan->idx_tail = 0;

Modified: head/sys/dev/xdma/xdma.h
==============================================================================
--- head/sys/dev/xdma/xdma.h	Mon Apr 29 16:26:29 2019	(r346895)
+++ head/sys/dev/xdma/xdma.h	Mon Apr 29 16:27:15 2019	(r346896)
@@ -84,7 +84,6 @@ struct xchan_buf {
 	bus_dmamap_t			map;
 	uint32_t			nsegs;
 	uint32_t			nsegs_left;
-	void				*cbuf;
 };
 
 struct xdma_request {
@@ -130,7 +129,8 @@ struct xdma_channel {
 
 	uint32_t			caps;
 #define	XCHAN_CAP_BUSDMA		(1 << 0)
-#define	XCHAN_CAP_BUSDMA_NOSEG		(1 << 1)
+#define	XCHAN_CAP_NOSEG			(1 << 1)
+#define	XCHAN_CAP_NOBUFS		(1 << 2)
 
 	/* A real hardware driver channel. */
 	void				*chan;

Modified: head/sys/dev/xdma/xdma_mbuf.c
==============================================================================
--- head/sys/dev/xdma/xdma_mbuf.c	Mon Apr 29 16:26:29 2019	(r346895)
+++ head/sys/dev/xdma/xdma_mbuf.c	Mon Apr 29 16:27:15 2019	(r346896)
@@ -136,19 +136,15 @@ xdma_mbuf_defrag(xdma_channel_t *xchan, struct xdma_re
 	if (c == 1)
 		return (c); /* Nothing to do. */
 
-	if (xchan->caps & XCHAN_CAP_BUSDMA) {
-		if ((xchan->caps & XCHAN_CAP_BUSDMA_NOSEG) || \
-		    (c > xchan->maxnsegs)) {
-			if ((m = m_defrag(xr->m, M_NOWAIT)) == NULL) {
-				device_printf(xdma->dma_dev,
-				    "%s: Can't defrag mbuf\n",
-				    __func__);
-				return (c);
-			}
-			xr->m = m;
-			c = 1;
-		}
+	if ((m = m_defrag(xr->m, M_NOWAIT)) == NULL) {
+		device_printf(xdma->dma_dev,
+		    "%s: Can't defrag mbuf\n",
+		    __func__);
+		return (c);
 	}
+
+	xr->m = m;
+	c = 1;
 
 	return (c);
 }

Modified: head/sys/dev/xdma/xdma_sg.c
==============================================================================
--- head/sys/dev/xdma/xdma_sg.c	Mon Apr 29 16:26:29 2019	(r346895)
+++ head/sys/dev/xdma/xdma_sg.c	Mon Apr 29 16:27:15 2019	(r346896)
@@ -69,14 +69,7 @@ _xchan_bufs_alloc(xdma_channel_t *xchan)
 
 	for (i = 0; i < xchan->xr_num; i++) {
 		xr = &xchan->xr_mem[i];
-		xr->buf.cbuf = contigmalloc(xchan->maxsegsize,
-		    M_XDMA, 0, 0, ~0, PAGE_SIZE, 0);
-		if (xr->buf.cbuf == NULL) {
-			device_printf(xdma->dev,
-			    "%s: Can't allocate contiguous kernel"
-			    " physical memory\n", __func__);
-			return (-1);
-		}
+		/* TODO: bounce buffer */
 	}
 
 	return (0);
@@ -179,7 +172,7 @@ xchan_bufs_free(xdma_channel_t *xchan)
 	} else {
 		for (i = 0; i < xchan->xr_num; i++) {
 			xr = &xchan->xr_mem[i];
-			contigfree(xr->buf.cbuf, xchan->maxsegsize, M_XDMA);
+			/* TODO: bounce buffer */
 		}
 	}
 
@@ -245,17 +238,19 @@ xdma_prep_sg(xdma_channel_t *xchan, uint32_t xr_num,
 		return (-1);
 	}
 
-	/* Allocate bufs. */
-	ret = xchan_bufs_alloc(xchan);
-	if (ret != 0) {
-		device_printf(xdma->dev,
-		    "%s: Can't allocate bufs.\n", __func__);
+	/* Allocate buffers if required. */
+	if ((xchan->caps & XCHAN_CAP_NOBUFS) == 0) {
+		ret = xchan_bufs_alloc(xchan);
+		if (ret != 0) {
+			device_printf(xdma->dev,
+			    "%s: Can't allocate bufs.\n", __func__);
 
-		/* Cleanup */
-		xchan_sglist_free(xchan);
-		xchan_bank_free(xchan);
+			/* Cleanup */
+			xchan_sglist_free(xchan);
+			xchan_bank_free(xchan);
 
-		return (-1);
+			return (-1);
+		}
 	}
 
 	xchan->flags |= (XCHAN_CONFIGURED | XCHAN_TYPE_SG);
@@ -442,14 +437,8 @@ _xdma_load_data(xdma_channel_t *xchan, struct xdma_req
 
 	switch (xr->req_type) {
 	case XR_TYPE_MBUF:
-		if (xr->direction == XDMA_MEM_TO_DEV) {
-			m_copydata(m, 0, m->m_pkthdr.len, xr->buf.cbuf);
-			seg[0].ds_addr = (bus_addr_t)xr->buf.cbuf;
-			seg[0].ds_len = m->m_pkthdr.len;
-		} else {
-			seg[0].ds_addr = mtod(m, bus_addr_t);
-			seg[0].ds_len = m->m_pkthdr.len;
-		}
+		seg[0].ds_addr = mtod(m, bus_addr_t);
+		seg[0].ds_len = m->m_pkthdr.len;
 		break;
 	case XR_TYPE_BIO:
 	case XR_TYPE_VIRT:
@@ -516,7 +505,9 @@ xdma_process(xdma_channel_t *xchan,
 	TAILQ_FOREACH_SAFE(xr, &xchan->queue_in, xr_next, xr_tmp) {
 		switch (xr->req_type) {
 		case XR_TYPE_MBUF:
-			c = xdma_mbuf_defrag(xchan, xr);
+			if ((xchan->caps & XCHAN_CAP_NOSEG) ||
+			    (c > xchan->maxnsegs))
+				c = xdma_mbuf_defrag(xchan, xr);
 			break;
 		case XR_TYPE_BIO:
 		case XR_TYPE_VIRT:
@@ -571,7 +562,8 @@ xdma_queue_submit_sg(xdma_channel_t *xchan)
 
 	sg = xchan->sg;
 
-	if ((xchan->flags & XCHAN_BUFS_ALLOCATED) == 0) {
+	if ((xchan->caps & XCHAN_CAP_NOBUFS) == 0 &&
+	   (xchan->flags & XCHAN_BUFS_ALLOCATED) == 0) {
 		device_printf(xdma->dev,
 		    "%s: Can't submit a transfer: no bufs\n",
 		    __func__);


More information about the svn-src-all mailing list