@@ -187,4 +187,14 @@
#define VHOST_VDPA_SET_VRING_ENABLE_BATCH _IOW(VHOST_VIRTIO, 0x7F, \
struct vhost_vring_state)
+/* Batch version of VHOST_VDPA_GET_VRING_GROUP
+ *
+ * Get the group for a virtqueue: read index, write group in num,
+ * The virtqueue index is stored in the index field of
+ * vhost_vring_state. The group for this specific virtqueue is
+ * returned via num field of vhost_vring_state while batching commands.
+ */
+#define VHOST_VDPA_GET_VRING_GROUP_BATCH _IOWR(VHOST_VIRTIO, 0x82, \
+ struct vhost_vring_state)
+
#endif
@@ -377,6 +377,47 @@ static int64_t vhost_vdpa_get_vring_group(int device_fd, unsigned vq_index)
return state.num;
}
+static int64_t vhost_vdpa_get_vring_group_batch(int device_fd, unsigned vq_index)
+{
+ int r;
+ struct vhost_vring_state states[vq_index + 1];
+ int64_t cvq_group;
+
+ states[0].num = vq_index;
+
+ for (int i = 1; i <= vq_index; ++i) {
+ states[i].index = i - 1;
+ }
+
+ r = ioctl(device_fd, VHOST_VDPA_GET_VRING_GROUP_BATCH, &states[0]);
+
+ if (unlikely(r < 0)) {
+ error_report("Cannot get VQ %d group: %s", vq_index - 1,
+ g_strerror(errno));
+ return r;
+ }
+
+ cvq_group = states[vq_index].num;
+
+ if (unlikely(cvq_group < 0)) {
+ return cvq_group;
+ }
+
+ for (int i = 1; i < vq_index; ++i) {
+ int64_t group = states[i].num;
+
+ if (unlikely(group < 0)) {
+ return group;
+ }
+
+ if (group == cvq_group) {
+ return 0;
+ }
+ }
+
+ return vq_index;
+}
+
static int vhost_vdpa_set_address_space_id(struct vhost_vdpa *v,
unsigned vq_group,
unsigned asid_num)
@@ -512,19 +553,28 @@ static int vhost_vdpa_net_cvq_start(NetClientState *nc)
* than the last vq. VQ group of last group passed in cvq_group.
*/
cvq_index = v->dev->vq_index_end - 1;
- cvq_group = vhost_vdpa_get_vring_group(v->device_fd, cvq_index);
- if (unlikely(cvq_group < 0)) {
- return cvq_group;
- }
- for (int i = 0; i < cvq_index; ++i) {
- int64_t group = vhost_vdpa_get_vring_group(v->device_fd, i);
- if (unlikely(group < 0)) {
- return group;
+ if (! (backend_features & BIT_ULL(VHOST_BACKEND_F_IOCTL_BATCH))) {
+ cvq_group = vhost_vdpa_get_vring_group(v->device_fd, cvq_index);
+ if (unlikely(cvq_group < 0)) {
+ return cvq_group;
}
+ for (int i = 0; i < cvq_index; ++i) {
+ int64_t group = vhost_vdpa_get_vring_group(v->device_fd, i);
- if (group == cvq_group) {
- return 0;
+ if (unlikely(group < 0)) {
+ return group;
+ }
+
+ if (group == cvq_group) {
+ return 0;
+ }
+ }
+ } else {
+ cvq_group = vhost_vdpa_get_vring_group_batch(v->device_fd, cvq_index + 1);
+
+ if (unlikely(cvq_group <= 0)) {
+ return cvq_group;
}
}