Blob Blame History Raw
--- 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)