Commit 20887611 authored by Rusty Russell's avatar Rusty Russell

lguest: notify on empty

This is the lguest implementation of the VIRTIO_F_NOTIFY_ON_EMPTY feature.
It is currently only published for network devices, but it is turned on for
everyone.
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent b4f68be6
...@@ -157,6 +157,9 @@ struct virtqueue ...@@ -157,6 +157,9 @@ struct virtqueue
/* The routine to call when the Guest pings us. */ /* The routine to call when the Guest pings us. */
void (*handle_output)(int fd, struct virtqueue *me); void (*handle_output)(int fd, struct virtqueue *me);
/* Outstanding buffers */
unsigned int inflight;
}; };
/* Remember the arguments to the program so we can "reboot" */ /* Remember the arguments to the program so we can "reboot" */
...@@ -702,6 +705,7 @@ static unsigned get_vq_desc(struct virtqueue *vq, ...@@ -702,6 +705,7 @@ static unsigned get_vq_desc(struct virtqueue *vq,
errx(1, "Looped descriptor"); errx(1, "Looped descriptor");
} while ((i = next_desc(vq, i)) != vq->vring.num); } while ((i = next_desc(vq, i)) != vq->vring.num);
vq->inflight++;
return head; return head;
} }
...@@ -719,6 +723,7 @@ static void add_used(struct virtqueue *vq, unsigned int head, int len) ...@@ -719,6 +723,7 @@ static void add_used(struct virtqueue *vq, unsigned int head, int len)
/* Make sure buffer is written before we update index. */ /* Make sure buffer is written before we update index. */
wmb(); wmb();
vq->vring.used->idx++; vq->vring.used->idx++;
vq->inflight--;
} }
/* This actually sends the interrupt for this virtqueue */ /* This actually sends the interrupt for this virtqueue */
...@@ -726,8 +731,9 @@ static void trigger_irq(int fd, struct virtqueue *vq) ...@@ -726,8 +731,9 @@ static void trigger_irq(int fd, struct virtqueue *vq)
{ {
unsigned long buf[] = { LHREQ_IRQ, vq->config.irq }; unsigned long buf[] = { LHREQ_IRQ, vq->config.irq };
/* If they don't want an interrupt, don't send one. */ /* If they don't want an interrupt, don't send one, unless empty. */
if (vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT) if ((vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
&& vq->inflight)
return; return;
/* Send the Guest an interrupt tell them we used something up. */ /* Send the Guest an interrupt tell them we used something up. */
...@@ -1107,6 +1113,7 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs, ...@@ -1107,6 +1113,7 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs,
vq->next = NULL; vq->next = NULL;
vq->last_avail_idx = 0; vq->last_avail_idx = 0;
vq->dev = dev; vq->dev = dev;
vq->inflight = 0;
/* Initialize the configuration. */ /* Initialize the configuration. */
vq->config.num = num_descs; vq->config.num = num_descs;
...@@ -1368,6 +1375,7 @@ static void setup_tun_net(const char *arg) ...@@ -1368,6 +1375,7 @@ static void setup_tun_net(const char *arg)
/* Tell Guest what MAC address to use. */ /* Tell Guest what MAC address to use. */
add_feature(dev, VIRTIO_NET_F_MAC); add_feature(dev, VIRTIO_NET_F_MAC);
add_feature(dev, VIRTIO_F_NOTIFY_ON_EMPTY);
set_config(dev, sizeof(conf), &conf); set_config(dev, sizeof(conf), &conf);
/* We don't need the socket any more; setup is done. */ /* We don't need the socket any more; setup is done. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment