From: Rusty Russell <rusty@rustcorp.com.au>
Subject: lguest: switch to using event counters.

Works, but need to run it on native (rather than under kvm) to see if
it effects performance.
---
 Documentation/virtual/lguest/Makefile |    2 -
 Documentation/virtual/lguest/lguest.c |   36 +++++++++++++++++-----------------
 2 files changed, 20 insertions(+), 18 deletions(-)

diff --git a/Documentation/virtual/lguest/Makefile b/Documentation/virtual/lguest/Makefile
--- a/Documentation/virtual/lguest/Makefile
+++ b/Documentation/virtual/lguest/Makefile
@@ -1,6 +1,6 @@
 # This creates the demonstration utility "lguest" which runs a Linux guest.
 # Missing headers?  Add "-I../../../include -I../../../arch/x86/include"
-CFLAGS:=-m32 -Wall -Wmissing-declarations -Wmissing-prototypes -O3 -U_FORTIFY_SOURCE
+CFLAGS:=-m32 -Wall -Wmissing-declarations -Wmissing-prototypes -g -U_FORTIFY_SOURCE -I../../../include -I../../../arch/x86/include
 
 all: lguest
 
diff --git a/Documentation/virtual/lguest/lguest.c b/Documentation/virtual/lguest/lguest.c
--- a/Documentation/virtual/lguest/lguest.c
+++ b/Documentation/virtual/lguest/lguest.c
@@ -626,19 +626,14 @@ static void trigger_irq(struct virtqueue
 {
 	unsigned long buf[] = { LHREQ_IRQ, vq->config.irq };
 
-	/* Don't inform them if nothing used. */
-	if (!vq->pending_used)
-		return;
-	vq->pending_used = 0;
-
-	/* If they don't want an interrupt, don't send one... */
-	if (vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT) {
-		return;
+	/* Send an interrupt if they asked for one at this point. */
+	if (vring_need_event(vring_used_event(&vq->vring),
+			     vq->vring.used->idx,
+			     vq->vring.used->idx - vq->pending_used)) {
+		if (write(lguest_fd, buf, sizeof(buf)) != 0)
+			err(1, "Triggering irq %i", vq->config.irq);
+		vq->pending_used = 0;
 	}
-
-	/* Send the Guest an interrupt tell them we used something up. */
-	if (write(lguest_fd, buf, sizeof(buf)) != 0)
-		err(1, "Triggering irq %i", vq->config.irq);
 }
 
 /*
@@ -668,7 +663,7 @@ static unsigned wait_for_vq_desc(struct 
 		trigger_irq(vq);
 
 		/* OK, now we need to know about added descriptors. */
-		vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
+		vring_used_event(&vq->vring) = last_avail + 1;
 
 		/*
 		 * They could have slipped one in as we were doing that: make
@@ -676,16 +671,12 @@ static unsigned wait_for_vq_desc(struct 
 		 */
 		mb();
 		if (last_avail != vq->vring.avail->idx) {
-			vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
 			break;
 		}
 
 		/* Nothing new?  Wait for eventfd to tell us they refilled. */
 		if (read(vq->eventfd, &event, sizeof(event)) != sizeof(event))
 			errx(1, "Event read failed?");
-
-		/* We don't need to be notified again. */
-		vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
 	}
 
 	/* Check it isn't doing very strange things with descriptor numbers. */
@@ -1349,6 +1340,9 @@ static void setup_console(void)
 	add_virtqueue(dev, VIRTQUEUE_NUM, console_input);
 	add_virtqueue(dev, VIRTQUEUE_NUM, console_output);
 
+	/* Every device must support VIRTIO_RING_F_EVENT_IDX. */
+	add_feature(dev, VIRTIO_RING_F_EVENT_IDX);
+
 	verbose("device %u: console\n", ++devices.device_num);
 }
 /*:*/
@@ -1546,6 +1540,8 @@ static void setup_tun_net(char *arg)
 	add_feature(dev, VIRTIO_NET_F_HOST_ECN);
 	/* We handle indirect ring entries */
 	add_feature(dev, VIRTIO_RING_F_INDIRECT_DESC);
+	/* Every device must support VIRTIO_RING_F_EVENT_IDX. */
+	add_feature(dev, VIRTIO_RING_F_EVENT_IDX);
 	set_config(dev, sizeof(conf), &conf);
 
 	/* We don't need the socket any more; setup is done. */
@@ -1718,6 +1714,9 @@ static void setup_block_file(const char 
 	add_feature(dev, VIRTIO_BLK_F_SEG_MAX);
 	conf.seg_max = cpu_to_le32(VIRTQUEUE_NUM - 2);
 
+	/* Every device must support VIRTIO_RING_F_EVENT_IDX. */
+	add_feature(dev, VIRTIO_RING_F_EVENT_IDX);
+
 	/* Don't try to put whole struct: we have 8 bit limit. */
 	set_config(dev, offsetof(struct virtio_blk_config, geometry), &conf);
 
@@ -1783,6 +1782,9 @@ static void setup_rng(void)
 	/* The device has one virtqueue, where the Guest places inbufs. */
 	add_virtqueue(dev, VIRTQUEUE_NUM, rng_input);
 
+	/* Every device must support VIRTIO_RING_F_EVENT_IDX. */
+	add_feature(dev, VIRTIO_RING_F_EVENT_IDX);
+
 	verbose("device %u: rng\n", devices.device_num++);
 }
 /* That's the end of device setup. */
