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>
This commit is contained in:
parent
2a4f26350c
commit
471fe8a252
|
@ -111,7 +111,6 @@ struct Stream {
|
||||||
int nr;
|
int nr;
|
||||||
|
|
||||||
struct SDesc desc;
|
struct SDesc desc;
|
||||||
int pos;
|
|
||||||
unsigned int complete_cnt;
|
unsigned int complete_cnt;
|
||||||
uint32_t regs[R_MAX];
|
uint32_t regs[R_MAX];
|
||||||
uint8_t app[20];
|
uint8_t app[20];
|
||||||
|
@ -267,7 +266,9 @@ static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev,
|
||||||
StreamSlave *tx_control_dev)
|
StreamSlave *tx_control_dev)
|
||||||
{
|
{
|
||||||
uint32_t prev_d;
|
uint32_t prev_d;
|
||||||
unsigned int txlen;
|
uint32_t txlen;
|
||||||
|
uint64_t addr;
|
||||||
|
bool eop;
|
||||||
|
|
||||||
if (!stream_running(s) || stream_idle(s)) {
|
if (!stream_running(s) || stream_idle(s)) {
|
||||||
return;
|
return;
|
||||||
|
@ -282,24 +283,26 @@ static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stream_desc_sof(&s->desc)) {
|
if (stream_desc_sof(&s->desc)) {
|
||||||
s->pos = 0;
|
|
||||||
stream_push(tx_control_dev, s->desc.app, sizeof(s->desc.app), true);
|
stream_push(tx_control_dev, s->desc.app, sizeof(s->desc.app), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
txlen = s->desc.control & SDESC_CTRL_LEN_MASK;
|
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__,
|
eop = stream_desc_eof(&s->desc);
|
||||||
txlen + s->pos);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
address_space_read(&s->dma->as, s->desc.buffer_address,
|
if (eop) {
|
||||||
MEMTXATTRS_UNSPECIFIED,
|
|
||||||
s->txbuf + s->pos, txlen);
|
|
||||||
s->pos += txlen;
|
|
||||||
|
|
||||||
if (stream_desc_eof(&s->desc)) {
|
|
||||||
stream_push(tx_data_dev, s->txbuf, s->pos, true);
|
|
||||||
s->pos = 0;
|
|
||||||
stream_complete(s);
|
stream_complete(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue