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: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
b4f68be6c5
commit
2088761152
|
@ -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,
|
||||||
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)
|
||||||
/* 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)
|
||||||
{
|
{
|
||||||
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,
|
||||||
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)
|
||||||
|
|
||||||
/* 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. */
|
||||||
|
|
Loading…
Reference in a new issue