Skip to content

Commit

Permalink
axienet: Flush queued packets when rx is done
Browse files Browse the repository at this point in the history
eth_can_rx checks s->rxsize and returns false if it is non-zero. Because
of the .can_receive semantics change, this will make the incoming queue
disabled by peer, until it is explicitly flushed. So we should flush it
when s->rxsize is becoming zero.

Squash eth_can_rx semantics into etx_rx and drop .can_receive()
callback, also add flush when rx buffer becomes available again after a
packet gets queued.

The other conditions, "!axienet_rx_resetting(s) &&
axienet_rx_enabled(s)" are OK because enet_write already calls
qemu_flush_queued_packets when the register bits are changed.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 1436955553-22791-13-git-send-email-famz@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
  • Loading branch information
Fam Zheng authored and stefanhaRH committed Jul 27, 2015
1 parent 4594f93 commit f9f7492
Showing 1 changed file with 13 additions and 4 deletions.
17 changes: 13 additions & 4 deletions hw/net/xilinx_axienet.c
Expand Up @@ -401,6 +401,9 @@ struct XilinxAXIEnet {

uint8_t rxapp[CONTROL_PAYLOAD_SIZE];
uint32_t rxappsize;

/* Whether axienet_eth_rx_notify should flush incoming queue. */
bool need_flush;
};

static void axienet_rx_reset(XilinxAXIEnet *s)
Expand Down Expand Up @@ -658,10 +661,8 @@ static const MemoryRegionOps enet_ops = {
.endianness = DEVICE_LITTLE_ENDIAN,
};

static int eth_can_rx(NetClientState *nc)
static int eth_can_rx(XilinxAXIEnet *s)
{
XilinxAXIEnet *s = qemu_get_nic_opaque(nc);

/* RX enabled? */
return !s->rxsize && !axienet_rx_resetting(s) && axienet_rx_enabled(s);
}
Expand Down Expand Up @@ -701,6 +702,10 @@ static void axienet_eth_rx_notify(void *opaque)
s->rxpos += ret;
if (!s->rxsize) {
s->regs[R_IS] |= IS_RX_COMPLETE;
if (s->need_flush) {
s->need_flush = false;
qemu_flush_queued_packets(qemu_get_queue(s->nic));
}
}
}
enet_update_irq(s);
Expand All @@ -721,6 +726,11 @@ static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)

DENET(qemu_log("%s: %zd bytes\n", __func__, size));

if (!eth_can_rx(s)) {
s->need_flush = true;
return 0;
}

unicast = ~buf[0] & 0x1;
broadcast = memcmp(buf, sa_bcast, 6) == 0;
multicast = !unicast && !broadcast;
Expand Down Expand Up @@ -925,7 +935,6 @@ xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size)
static NetClientInfo net_xilinx_enet_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
.can_receive = eth_can_rx,
.receive = eth_rx,
};

Expand Down

0 comments on commit f9f7492

Please sign in to comment.