@@ -332,6 +332,37 @@ int vring_pop(VirtIODevice *vdev, Vring *vring,
return head;
}
+/* Same as vring_push, but delay update used->idx, until ready */
+void vring_fill(Vring *vring, unsigned int head, int len)
+{
+ struct vring_used_elem *used;
+
+ /* Don't touch vring if a fatal error occurred */
+ if (vring->broken) {
+ return;
+ }
+
+ /* The virtqueue contains a ring of used buffers. Get a pointer to the
+ * next entry in that used ring. */
+ used = &vring->vr.used->ring[vring->last_used_idx % vring->vr.num];
+ used->id = head;
+ used->len = len;
+ vring->last_used_idx++;
+}
+
+void vring_flush(Vring *vring)
+{
+ uint16_t new;
+
+ /* Make sure buffer is written before we update index. */
+ smp_wmb();
+
+ new = vring->vr.used->idx = vring->last_used_idx;
+ if (unlikely((int16_t)(new - vring->signalled_used) < (uint16_t)1)) {
+ vring->signalled_used_valid = false;
+ }
+}
+
/* After we've used one of their buffers, we tell them about it.
*
* Stolen from linux/drivers/vhost/vhost.c.
@@ -57,6 +57,8 @@ bool vring_should_notify(VirtIODevice *vdev, Vring *vring);
int vring_pop(VirtIODevice *vdev, Vring *vring,
struct iovec iov[], struct iovec *iov_end,
unsigned int *out_num, unsigned int *in_num);
+void vring_fill(Vring *vring, unsigned int head, int len);
+void vring_flush(Vring *vring);
void vring_push(Vring *vring, unsigned int head, int len);
#endif /* VRING_H */