svn commit: r348619 - in stable/12/sys/dev: altera/atse altera/softdma xdma
Ruslan Bukin
br at FreeBSD.org
Tue Jun 4 15:28:35 UTC 2019
Author: br
Date: Tue Jun 4 15:28:32 2019
New Revision: 348619
URL: https://svnweb.freebsd.org/changeset/base/348619
Log:
MFC r346896:
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:
stable/12/sys/dev/altera/atse/if_atse.c
stable/12/sys/dev/altera/softdma/softdma.c
stable/12/sys/dev/xdma/xdma.h
stable/12/sys/dev/xdma/xdma_mbuf.c
stable/12/sys/dev/xdma/xdma_sg.c
Modified: stable/12/sys/dev/altera/atse/if_atse.c
==============================================================================
--- stable/12/sys/dev/altera/atse/if_atse.c Tue Jun 4 15:26:02 2019 (r348618)
+++ stable/12/sys/dev/altera/atse/if_atse.c Tue Jun 4 15:28:32 2019 (r348619)
@@ -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: stable/12/sys/dev/altera/softdma/softdma.c
==============================================================================
--- stable/12/sys/dev/altera/softdma/softdma.c Tue Jun 4 15:26:02 2019 (r348618)
+++ stable/12/sys/dev/altera/softdma/softdma.c Tue Jun 4 15:28:32 2019 (r348619)
@@ -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: stable/12/sys/dev/xdma/xdma.h
==============================================================================
--- stable/12/sys/dev/xdma/xdma.h Tue Jun 4 15:26:02 2019 (r348618)
+++ stable/12/sys/dev/xdma/xdma.h Tue Jun 4 15:28:32 2019 (r348619)
@@ -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: stable/12/sys/dev/xdma/xdma_mbuf.c
==============================================================================
--- stable/12/sys/dev/xdma/xdma_mbuf.c Tue Jun 4 15:26:02 2019 (r348618)
+++ stable/12/sys/dev/xdma/xdma_mbuf.c Tue Jun 4 15:28:32 2019 (r348619)
@@ -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: stable/12/sys/dev/xdma/xdma_sg.c
==============================================================================
--- stable/12/sys/dev/xdma/xdma_sg.c Tue Jun 4 15:26:02 2019 (r348618)
+++ stable/12/sys/dev/xdma/xdma_sg.c Tue Jun 4 15:28:32 2019 (r348619)
@@ -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-stable-12
mailing list