diff options
author | Edgar E. Iglesias <edgar.iglesias@xilinx.com> | 2020-05-06 10:25:11 +0200 |
---|---|---|
committer | Edgar E. Iglesias <edgar.iglesias@xilinx.com> | 2020-05-14 13:44:35 +0200 |
commit | 471fe8a2520272253adec1cc099e26f04958e301 (patch) | |
tree | fc356423be04667190e499126e6c351bb47b95c7 /hw/dma | |
parent | 2a4f26350c53f9f48d0245254d7af0c55a1d22fe (diff) |
hw/dma/xilinx_axidma: mm2s: Stream descriptor by descriptor
Stream descriptor by descriptor from memory instead of
buffering entire packets before pushing. This enables
non-packet streaming clients to work and also lifts the
limitation that our internal DMA buffer needs to be able
to hold entire packets.
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-Id: <20200506082513.18751-8-edgar.iglesias@gmail.com>
Diffstat (limited to 'hw/dma')
-rw-r--r-- | hw/dma/xilinx_axidma.c | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c index a770e12c96..101d32a965 100644 --- a/hw/dma/xilinx_axidma.c +++ b/hw/dma/xilinx_axidma.c @@ -111,7 +111,6 @@ struct Stream { int nr; struct SDesc desc; - int pos; unsigned int complete_cnt; uint32_t regs[R_MAX]; uint8_t app[20]; @@ -267,7 +266,9 @@ static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev, StreamSlave *tx_control_dev) { uint32_t prev_d; - unsigned int txlen; + uint32_t txlen; + uint64_t addr; + bool eop; if (!stream_running(s) || stream_idle(s)) { return; @@ -282,24 +283,26 @@ static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev, } if (stream_desc_sof(&s->desc)) { - s->pos = 0; stream_push(tx_control_dev, s->desc.app, sizeof(s->desc.app), true); } txlen = s->desc.control & SDESC_CTRL_LEN_MASK; - if ((txlen + s->pos) > sizeof s->txbuf) { - hw_error("%s: too small internal txbuf! %d\n", __func__, - txlen + s->pos); - } - address_space_read(&s->dma->as, s->desc.buffer_address, - MEMTXATTRS_UNSPECIFIED, - s->txbuf + s->pos, txlen); - s->pos += txlen; + eop = stream_desc_eof(&s->desc); + addr = s->desc.buffer_address; + while (txlen) { + unsigned int len; + + len = txlen > sizeof s->txbuf ? sizeof s->txbuf : txlen; + address_space_read(&s->dma->as, addr, + MEMTXATTRS_UNSPECIFIED, + s->txbuf, len); + stream_push(tx_data_dev, s->txbuf, len, eop && len == txlen); + txlen -= len; + addr += len; + } - if (stream_desc_eof(&s->desc)) { - stream_push(tx_data_dev, s->txbuf, s->pos, true); - s->pos = 0; + if (eop) { stream_complete(s); } |