--- xen-4.5.1/tools/qemu-xen-traditional/hw/virtio.c.orig 2015-06-09 16:32:24.000000000 +0100 +++ xen-4.5.1/tools/qemu-xen-traditional/hw/virtio.c 2015-10-10 16:57:01.806370020 +0100 @@ -268,8 +268,8 @@ return vring_avail_idx(vq) == vq->last_avail_idx; } -void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem, - unsigned int len, unsigned int idx) +static void virtqueue_unmap_sg(VirtQueue *vq, const VirtQueueElement *elem, + unsigned int len) { unsigned int offset; int i; @@ -302,7 +302,19 @@ offset += size; } +} +void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem, + unsigned int len) +{ + vq->last_avail_idx--; + virtqueue_unmap_sg(vq, elem, len); +} + +void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem, + unsigned int len, unsigned int idx) +{ + virtqueue_unmap_sg(vq, elem, len); idx = (idx + vring_used_idx(vq)) % vq->vring.num; /* Get a pointer to the next entry in the used ring. */ --- xen-4.5.1/tools/qemu-xen-traditional/hw/virtio.h.orig 2015-06-09 16:32:24.000000000 +0100 +++ xen-4.5.1/tools/qemu-xen-traditional/hw/virtio.h 2015-10-10 16:57:53.146216039 +0100 @@ -105,6 +105,8 @@ void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem, unsigned int len); void virtqueue_flush(VirtQueue *vq, unsigned int count); +void virtqueue_discard(VirtQueue *vq, const VirtQueueElement *elem, + unsigned int len); void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem, unsigned int len, unsigned int idx); --- xen-4.5.1/tools/qemu-xen-traditional/hw/virtio-net.c.orig 2015-10-10 16:10:05.071786348 +0100 +++ xen-4.5.1/tools/qemu-xen-traditional/hw/virtio-net.c 2015-10-10 19:05:34.510029916 +0100 @@ -424,11 +424,15 @@ len = iov_fill(sg, elem.in_num, buf + offset, size - offset); total += len; + offset += len; + if (!n->mergeable_rx_bufs && offset < size) { + virtqueue_discard(n->rx_vq, &elem, total); + return; + } /* signal other side */ virtqueue_fill(n->rx_vq, &elem, total, i++); - offset += len; } if (mhdr)