stellaris_enet: Flush queued packets when read done

If s->np reaches 31, the queue will be disabled by peer when it sees
stellaris_enet_can_receive() returns false, until we explicitly flushes
it which notifies the peer. Do this when guest is done reading all
existing data.

Move the semantics to stellaris_enet_receive, by returning 0 when the
buffer is full, so that new packets will be queued.  In
stellaris_enet_read, flush and restart the queue when guest has done
reading.

Signed-off-by: Fam Zheng <famz@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Jason Wang <jasowang@redhat.com>
Message-id: 1436955553-22791-11-git-send-email-famz@redhat.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Fam Zheng 2015-07-15 18:19:11 +08:00 committed by Stefan Hajnoczi
parent 1dd58ae058
commit 1ef4a6069f

View File

@ -228,8 +228,7 @@ static ssize_t stellaris_enet_receive(NetClientState *nc, const uint8_t *buf, si
if ((s->rctl & SE_RCTL_RXEN) == 0) if ((s->rctl & SE_RCTL_RXEN) == 0)
return -1; return -1;
if (s->np >= 31) { if (s->np >= 31) {
DPRINTF("Packet dropped\n"); return 0;
return -1;
} }
DPRINTF("Received packet len=%zu\n", size); DPRINTF("Received packet len=%zu\n", size);
@ -260,13 +259,8 @@ static ssize_t stellaris_enet_receive(NetClientState *nc, const uint8_t *buf, si
return size; return size;
} }
static int stellaris_enet_can_receive(NetClientState *nc) static int stellaris_enet_can_receive(stellaris_enet_state *s)
{ {
stellaris_enet_state *s = qemu_get_nic_opaque(nc);
if ((s->rctl & SE_RCTL_RXEN) == 0)
return 1;
return (s->np < 31); return (s->np < 31);
} }
@ -307,6 +301,9 @@ static uint64_t stellaris_enet_read(void *opaque, hwaddr offset,
s->next_packet = 0; s->next_packet = 0;
s->np--; s->np--;
DPRINTF("RX done np=%d\n", s->np); DPRINTF("RX done np=%d\n", s->np);
if (!s->np && stellaris_enet_can_receive(s)) {
qemu_flush_queued_packets(qemu_get_queue(s->nic));
}
} }
return val; return val;
} }
@ -454,7 +451,6 @@ static void stellaris_enet_reset(stellaris_enet_state *s)
static NetClientInfo net_stellaris_enet_info = { static NetClientInfo net_stellaris_enet_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.can_receive = stellaris_enet_can_receive,
.receive = stellaris_enet_receive, .receive = stellaris_enet_receive,
}; };