hw/core: stream: Add an end-of-packet flag

Some stream clients stream an endless stream of data while
other clients stream data in packets. Stream interfaces
usually have a way to signal the end of a packet or the
last beat of a transfer.

This adds an end-of-packet flag to the push interface.

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
Message-Id: <20200506082513.18751-6-edgar.iglesias@gmail.com>
This commit is contained in:
Edgar E. Iglesias 2020-05-06 10:25:09 +02:00
parent e3a8926d0e
commit 51b19950ca
5 changed files with 22 additions and 13 deletions

View File

@ -3,11 +3,11 @@
#include "qemu/module.h" #include "qemu/module.h"
size_t size_t
stream_push(StreamSlave *sink, uint8_t *buf, size_t len) stream_push(StreamSlave *sink, uint8_t *buf, size_t len, bool eop)
{ {
StreamSlaveClass *k = STREAM_SLAVE_GET_CLASS(sink); StreamSlaveClass *k = STREAM_SLAVE_GET_CLASS(sink);
return k->push(sink, buf, len); return k->push(sink, buf, len, eop);
} }
bool bool

View File

@ -283,7 +283,7 @@ 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; s->pos = 0;
stream_push(tx_control_dev, s->desc.app, sizeof(s->desc.app)); 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;
@ -298,7 +298,7 @@ static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev,
s->pos += txlen; s->pos += txlen;
if (stream_desc_eof(&s->desc)) { if (stream_desc_eof(&s->desc)) {
stream_push(tx_data_dev, s->txbuf, s->pos); stream_push(tx_data_dev, s->txbuf, s->pos, true);
s->pos = 0; s->pos = 0;
stream_complete(s); stream_complete(s);
} }
@ -384,7 +384,7 @@ static void xilinx_axidma_reset(DeviceState *dev)
static size_t static size_t
xilinx_axidma_control_stream_push(StreamSlave *obj, unsigned char *buf, xilinx_axidma_control_stream_push(StreamSlave *obj, unsigned char *buf,
size_t len) size_t len, bool eop)
{ {
XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM(obj); XilinxAXIDMAStreamSlave *cs = XILINX_AXI_DMA_CONTROL_STREAM(obj);
struct Stream *s = &cs->dma->streams[1]; struct Stream *s = &cs->dma->streams[1];
@ -416,12 +416,14 @@ xilinx_axidma_data_stream_can_push(StreamSlave *obj,
} }
static size_t static size_t
xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len) xilinx_axidma_data_stream_push(StreamSlave *obj, unsigned char *buf, size_t len,
bool eop)
{ {
XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj); XilinxAXIDMAStreamSlave *ds = XILINX_AXI_DMA_DATA_STREAM(obj);
struct Stream *s = &ds->dma->streams[1]; struct Stream *s = &ds->dma->streams[1];
size_t ret; size_t ret;
assert(eop);
ret = stream_process_s2mem(s, buf, len); ret = stream_process_s2mem(s, buf, len);
stream_update_irq(s); stream_update_irq(s);
return ret; return ret;

View File

@ -697,14 +697,14 @@ static void axienet_eth_rx_notify(void *opaque)
axienet_eth_rx_notify, s)) { axienet_eth_rx_notify, s)) {
size_t ret = stream_push(s->tx_control_dev, size_t ret = stream_push(s->tx_control_dev,
(void *)s->rxapp + CONTROL_PAYLOAD_SIZE (void *)s->rxapp + CONTROL_PAYLOAD_SIZE
- s->rxappsize, s->rxappsize); - s->rxappsize, s->rxappsize, true);
s->rxappsize -= ret; s->rxappsize -= ret;
} }
while (s->rxsize && stream_can_push(s->tx_data_dev, while (s->rxsize && stream_can_push(s->tx_data_dev,
axienet_eth_rx_notify, s)) { axienet_eth_rx_notify, s)) {
size_t ret = stream_push(s->tx_data_dev, (void *)s->rxmem + s->rxpos, size_t ret = stream_push(s->tx_data_dev, (void *)s->rxmem + s->rxpos,
s->rxsize); s->rxsize, true);
s->rxsize -= ret; s->rxsize -= ret;
s->rxpos += ret; s->rxpos += ret;
if (!s->rxsize) { if (!s->rxsize) {
@ -874,12 +874,14 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
} }
static size_t static size_t
xilinx_axienet_control_stream_push(StreamSlave *obj, uint8_t *buf, size_t len) xilinx_axienet_control_stream_push(StreamSlave *obj, uint8_t *buf, size_t len,
bool eop)
{ {
int i; int i;
XilinxAXIEnetStreamSlave *cs = XILINX_AXI_ENET_CONTROL_STREAM(obj); XilinxAXIEnetStreamSlave *cs = XILINX_AXI_ENET_CONTROL_STREAM(obj);
XilinxAXIEnet *s = cs->enet; XilinxAXIEnet *s = cs->enet;
assert(eop);
if (len != CONTROL_PAYLOAD_SIZE) { if (len != CONTROL_PAYLOAD_SIZE) {
hw_error("AXI Enet requires %d byte control stream payload\n", hw_error("AXI Enet requires %d byte control stream payload\n",
(int)CONTROL_PAYLOAD_SIZE); (int)CONTROL_PAYLOAD_SIZE);
@ -894,11 +896,15 @@ xilinx_axienet_control_stream_push(StreamSlave *obj, uint8_t *buf, size_t len)
} }
static size_t static size_t
xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size) xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size,
bool eop)
{ {
XilinxAXIEnetStreamSlave *ds = XILINX_AXI_ENET_DATA_STREAM(obj); XilinxAXIEnetStreamSlave *ds = XILINX_AXI_ENET_DATA_STREAM(obj);
XilinxAXIEnet *s = ds->enet; XilinxAXIEnet *s = ds->enet;
/* We don't support fragmented packets yet. */
assert(eop);
/* TX enable ? */ /* TX enable ? */
if (!(s->tc & TC_TX)) { if (!(s->tc & TC_TX)) {
return size; return size;

View File

@ -868,7 +868,7 @@ static void xlnx_zynqmp_qspips_notify(void *opaque)
memcpy(rq->dma_buf, rxd, num); memcpy(rq->dma_buf, rxd, num);
ret = stream_push(rq->dma, rq->dma_buf, num); ret = stream_push(rq->dma, rq->dma_buf, num, false);
assert(ret == num); assert(ret == num);
xlnx_zynqmp_qspips_check_flush(rq); xlnx_zynqmp_qspips_check_flush(rq);
} }

View File

@ -39,12 +39,13 @@ typedef struct StreamSlaveClass {
* @obj: Stream slave to push to * @obj: Stream slave to push to
* @buf: Data to write * @buf: Data to write
* @len: Maximum number of bytes to write * @len: Maximum number of bytes to write
* @eop: End of packet flag
*/ */
size_t (*push)(StreamSlave *obj, unsigned char *buf, size_t len); size_t (*push)(StreamSlave *obj, unsigned char *buf, size_t len, bool eop);
} StreamSlaveClass; } StreamSlaveClass;
size_t size_t
stream_push(StreamSlave *sink, uint8_t *buf, size_t len); stream_push(StreamSlave *sink, uint8_t *buf, size_t len, bool eop);
bool bool
stream_can_push(StreamSlave *sink, StreamCanPushNotifyFn notify, stream_can_push(StreamSlave *sink, StreamCanPushNotifyFn notify,