|
@@ -744,6 +744,60 @@ int virtio_queue_empty(VirtQueue *vq)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static bool virtio_queue_split_poll(VirtQueue *vq, unsigned shadow_idx)
|
|
|
+{
|
|
|
+ if (unlikely(!vq->vring.avail)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (uint16_t)shadow_idx != vring_avail_idx(vq);
|
|
|
+}
|
|
|
+
|
|
|
+static bool virtio_queue_packed_poll(VirtQueue *vq, unsigned shadow_idx)
|
|
|
+{
|
|
|
+ VRingPackedDesc desc;
|
|
|
+ VRingMemoryRegionCaches *caches;
|
|
|
+
|
|
|
+ if (unlikely(!vq->vring.desc)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ caches = vring_get_region_caches(vq);
|
|
|
+ if (!caches) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ vring_packed_desc_read(vq->vdev, &desc, &caches->desc,
|
|
|
+ shadow_idx, true);
|
|
|
+
|
|
|
+ return is_desc_avail(desc.flags, vq->shadow_avail_wrap_counter);
|
|
|
+}
|
|
|
+
|
|
|
+static bool virtio_queue_poll(VirtQueue *vq, unsigned shadow_idx)
|
|
|
+{
|
|
|
+ if (virtio_device_disabled(vq->vdev)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (virtio_vdev_has_feature(vq->vdev, VIRTIO_F_RING_PACKED)) {
|
|
|
+ return virtio_queue_packed_poll(vq, shadow_idx);
|
|
|
+ } else {
|
|
|
+ return virtio_queue_split_poll(vq, shadow_idx);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+bool virtio_queue_enable_notification_and_check(VirtQueue *vq,
|
|
|
+ int opaque)
|
|
|
+{
|
|
|
+ virtio_queue_set_notification(vq, 1);
|
|
|
+
|
|
|
+ if (opaque >= 0) {
|
|
|
+ return virtio_queue_poll(vq, (unsigned)opaque);
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static void virtqueue_unmap_sg(VirtQueue *vq, const VirtQueueElement *elem,
|
|
|
unsigned int len)
|
|
|
{
|
|
@@ -1442,9 +1496,9 @@ err:
|
|
|
goto done;
|
|
|
}
|
|
|
|
|
|
-void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,
|
|
|
- unsigned int *out_bytes,
|
|
|
- unsigned max_in_bytes, unsigned max_out_bytes)
|
|
|
+int virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,
|
|
|
+ unsigned int *out_bytes, unsigned max_in_bytes,
|
|
|
+ unsigned max_out_bytes)
|
|
|
{
|
|
|
uint16_t desc_size;
|
|
|
VRingMemoryRegionCaches *caches;
|
|
@@ -1477,7 +1531,7 @@ void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,
|
|
|
caches);
|
|
|
}
|
|
|
|
|
|
- return;
|
|
|
+ return (int)vq->shadow_avail_idx;
|
|
|
err:
|
|
|
if (in_bytes) {
|
|
|
*in_bytes = 0;
|
|
@@ -1485,6 +1539,8 @@ err:
|
|
|
if (out_bytes) {
|
|
|
*out_bytes = 0;
|
|
|
}
|
|
|
+
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes,
|