* THE SOFTWARE.
*/
+#include "qemu/osdep.h"
#include "hw/sysbus.h"
+#include "qapi/error.h"
#include "qemu/log.h"
#include "net/net.h"
#include "net/checksum.h"
-#include "qapi/qmp/qerror.h"
#include "hw/stream.h"
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)
.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);
}
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);
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;
return size;
}
-static void eth_cleanup(NetClientState *nc)
-{
- /* FIXME. */
- XilinxAXIEnet *s = qemu_get_nic_opaque(nc);
- g_free(s->rxmem);
- g_free(s);
-}
-
static size_t
xilinx_axienet_control_stream_push(StreamSlave *obj, uint8_t *buf, size_t len)
{
}
static NetClientInfo net_xilinx_enet_info = {
- .type = NET_CLIENT_OPTIONS_KIND_NIC,
+ .type = NET_CLIENT_DRIVER_NIC,
.size = sizeof(NICState),
- .can_receive = eth_can_rx,
.receive = eth_rx,
- .cleanup = eth_cleanup,
};
static void xilinx_enet_realize(DeviceState *dev, Error **errp)