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:
parent
e3a8926d0e
commit
51b19950ca
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user