@@ -110,7 +110,8 @@ static int s390_virtio_net_init(VirtIOS390Device *dev)
{
VirtIODevice *vdev;
- vdev = virtio_net_init((DeviceState *)dev, &dev->nic, dev->txtimer);
+ vdev = virtio_net_init((DeviceState *)dev, &dev->nic,
+ dev->txtimer, dev->txburst);
if (!vdev) {
return -1;
}
@@ -328,6 +329,7 @@ static VirtIOS390DeviceInfo s390_virtio_net = {
.qdev.props = (Property[]) {
DEFINE_NIC_PROPERTIES(VirtIOS390Device, nic),
DEFINE_PROP_UINT32("txtimer", VirtIOS390Device, txtimer, 1),
+ DEFINE_PROP_INT32("txburst", VirtIOS390Device, txburst, 256),
DEFINE_PROP_END_OF_LIST(),
},
};
@@ -45,6 +45,8 @@ typedef struct VirtIOS390Device {
uint32_t max_virtserial_ports;
/* Timeout value for virtio-net txtimer, 1 = default, >1 = ns timeout */
uint32_t txtimer;
+ /* Max tx packets for virtio-net to burst at a time */
+ int32_t txburst;
} VirtIOS390Device;
typedef struct VirtIOS390Bus {
@@ -70,6 +70,8 @@ typedef struct {
uint32_t host_features;
/* Timeout value for virtio-net txtimer, 1 = default, >1 = ns timeout */
uint32_t txtimer;
+ /* Max tx packets for virtio-net to burst at a time */
+ int32_t txburst;
} SyborgVirtIOProxy;
static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset)
@@ -286,7 +288,8 @@ static int syborg_virtio_net_init(SysBusDevice *dev)
VirtIODevice *vdev;
SyborgVirtIOProxy *proxy = FROM_SYSBUS(SyborgVirtIOProxy, dev);
- vdev = virtio_net_init(&dev->qdev, &proxy->nic, proxy->txtimer);
+ vdev = virtio_net_init(&dev->qdev, &proxy->nic,
+ proxy->txtimer, proxy->txburst);
return syborg_virtio_init(proxy, vdev);
}
@@ -298,6 +301,7 @@ static SysBusDeviceInfo syborg_virtio_net_info = {
DEFINE_NIC_PROPERTIES(SyborgVirtIOProxy, nic),
DEFINE_VIRTIO_NET_FEATURES(SyborgVirtIOProxy, host_features),
DEFINE_PROP_UINT32("txtimer", SyborgVirtIOProxy, txtimer, 1),
+ DEFINE_PROP_INT32("txburst", SyborgVirtIOProxy, txburst, 256),
DEFINE_PROP_END_OF_LIST(),
}
};
@@ -37,6 +37,7 @@ typedef struct VirtIONet
NICState *nic;
QEMUTimer *tx_timer;
uint32_t tx_timeout;
+ int32_t tx_burst;
int tx_timer_active;
uint32_t has_vnet_hdr;
uint8_t has_ufo;
@@ -620,7 +621,7 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_
return size;
}
-static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq);
+static int32_t virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq);
static void virtio_net_tx_complete(VLANClientState *nc, ssize_t len)
{
@@ -636,16 +637,18 @@ static void virtio_net_tx_complete(VLANClientState *nc, ssize_t len)
}
/* TX */
-static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
+static int32_t virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
{
VirtQueueElement elem;
+ int32_t num_packets = 0;
- if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
- return;
+ if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) {
+ return num_packets;
+ }
if (n->async_tx.elem.out_num) {
virtio_queue_set_notification(n->tx_vq, 0);
- return;
+ return num_packets;
}
while (virtqueue_pop(vq, &elem)) {
@@ -682,14 +685,19 @@ static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
virtio_queue_set_notification(n->tx_vq, 0);
n->async_tx.elem = elem;
n->async_tx.len = len;
- return;
+ return -EBUSY;
}
len += ret;
virtqueue_push(vq, &elem, len);
virtio_notify(&n->vdev, vq);
+
+ if (++num_packets >= n->tx_burst) {
+ break;
+ }
}
+ return num_packets;
}
static void virtio_net_handle_tx(VirtIODevice *vdev, VirtQueue *vq)
@@ -905,7 +913,7 @@ static void virtio_net_vmstate_change(void *opaque, int running, int reason)
}
VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
- uint32_t txtimer)
+ uint32_t txtimer, int32_t txburst)
{
VirtIONet *n;
@@ -942,6 +950,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
n->tx_timeout = txtimer;
}
}
+ n->tx_burst = txburst;
n->mergeable_rx_bufs = 0;
n->promisc = 1; /* for compatibility */
@@ -109,6 +109,8 @@ typedef struct {
uint32_t max_virtserial_ports;
/* Timeout value for virtio-net txtimer, 1 = default, >1 = ns timeout */
uint32_t txtimer;
+ /* Max tx packets for virtio-net to burst at a time */
+ int32_t txburst;
} VirtIOPCIProxy;
/* virtio device */
@@ -615,7 +617,8 @@ static int virtio_net_init_pci(PCIDevice *pci_dev)
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
VirtIODevice *vdev;
- vdev = virtio_net_init(&pci_dev->qdev, &proxy->nic, proxy->txtimer);
+ vdev = virtio_net_init(&pci_dev->qdev, &proxy->nic,
+ proxy->txtimer, proxy->txburst);
vdev->nvectors = proxy->nvectors;
virtio_init_pci(proxy, vdev,
@@ -693,6 +696,7 @@ static PCIDeviceInfo virtio_info[] = {
DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
DEFINE_PROP_UINT32("txtimer", VirtIOPCIProxy, txtimer, 1),
+ DEFINE_PROP_INT32("txburst", VirtIOPCIProxy, txburst, 256),
DEFINE_PROP_END_OF_LIST(),
},
.qdev.reset = virtio_pci_reset,
@@ -186,7 +186,7 @@ void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
/* Base devices. */
VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf);
VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
- uint32_t txtimer);
+ uint32_t txtimer, int32_t txburst);
VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports);
VirtIODevice *virtio_balloon_init(DeviceState *dev);
#ifdef CONFIG_LINUX