|
@@ -1777,15 +1777,36 @@ int vhost_dev_get_inflight(struct vhost_dev *dev, uint16_t queue_size,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int vhost_dev_set_vring_enable(struct vhost_dev *hdev, int enable)
|
|
|
|
+{
|
|
|
|
+ if (!hdev->vhost_ops->vhost_set_vring_enable) {
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * For vhost-user devices, if VHOST_USER_F_PROTOCOL_FEATURES has not
|
|
|
|
+ * been negotiated, the rings start directly in the enabled state, and
|
|
|
|
+ * .vhost_set_vring_enable callback will fail since
|
|
|
|
+ * VHOST_USER_SET_VRING_ENABLE is not supported.
|
|
|
|
+ */
|
|
|
|
+ if (hdev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER &&
|
|
|
|
+ !virtio_has_feature(hdev->backend_features,
|
|
|
|
+ VHOST_USER_F_PROTOCOL_FEATURES)) {
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return hdev->vhost_ops->vhost_set_vring_enable(hdev, enable);
|
|
|
|
+}
|
|
|
|
+
|
|
/* Host notifiers must be enabled at this point. */
|
|
/* Host notifiers must be enabled at this point. */
|
|
-int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
|
|
|
|
|
|
+int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings)
|
|
{
|
|
{
|
|
int i, r;
|
|
int i, r;
|
|
|
|
|
|
/* should only be called after backend is connected */
|
|
/* should only be called after backend is connected */
|
|
assert(hdev->vhost_ops);
|
|
assert(hdev->vhost_ops);
|
|
|
|
|
|
- trace_vhost_dev_start(hdev, vdev->name);
|
|
|
|
|
|
+ trace_vhost_dev_start(hdev, vdev->name, vrings);
|
|
|
|
|
|
vdev->vhost_started = true;
|
|
vdev->vhost_started = true;
|
|
hdev->started = true;
|
|
hdev->started = true;
|
|
@@ -1830,10 +1851,16 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
|
|
goto fail_log;
|
|
goto fail_log;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ if (vrings) {
|
|
|
|
+ r = vhost_dev_set_vring_enable(hdev, true);
|
|
|
|
+ if (r) {
|
|
|
|
+ goto fail_log;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
if (hdev->vhost_ops->vhost_dev_start) {
|
|
if (hdev->vhost_ops->vhost_dev_start) {
|
|
r = hdev->vhost_ops->vhost_dev_start(hdev, true);
|
|
r = hdev->vhost_ops->vhost_dev_start(hdev, true);
|
|
if (r) {
|
|
if (r) {
|
|
- goto fail_log;
|
|
|
|
|
|
+ goto fail_start;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (vhost_dev_has_iommu(hdev) &&
|
|
if (vhost_dev_has_iommu(hdev) &&
|
|
@@ -1848,6 +1875,10 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
return 0;
|
|
|
|
+fail_start:
|
|
|
|
+ if (vrings) {
|
|
|
|
+ vhost_dev_set_vring_enable(hdev, false);
|
|
|
|
+ }
|
|
fail_log:
|
|
fail_log:
|
|
vhost_log_put(hdev, false);
|
|
vhost_log_put(hdev, false);
|
|
fail_vq:
|
|
fail_vq:
|
|
@@ -1866,18 +1897,21 @@ fail_features:
|
|
}
|
|
}
|
|
|
|
|
|
/* Host notifiers must be enabled at this point. */
|
|
/* Host notifiers must be enabled at this point. */
|
|
-void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
|
|
|
|
|
|
+void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings)
|
|
{
|
|
{
|
|
int i;
|
|
int i;
|
|
|
|
|
|
/* should only be called after backend is connected */
|
|
/* should only be called after backend is connected */
|
|
assert(hdev->vhost_ops);
|
|
assert(hdev->vhost_ops);
|
|
|
|
|
|
- trace_vhost_dev_stop(hdev, vdev->name);
|
|
|
|
|
|
+ trace_vhost_dev_stop(hdev, vdev->name, vrings);
|
|
|
|
|
|
if (hdev->vhost_ops->vhost_dev_start) {
|
|
if (hdev->vhost_ops->vhost_dev_start) {
|
|
hdev->vhost_ops->vhost_dev_start(hdev, false);
|
|
hdev->vhost_ops->vhost_dev_start(hdev, false);
|
|
}
|
|
}
|
|
|
|
+ if (vrings) {
|
|
|
|
+ vhost_dev_set_vring_enable(hdev, false);
|
|
|
|
+ }
|
|
for (i = 0; i < hdev->nvqs; ++i) {
|
|
for (i = 0; i < hdev->nvqs; ++i) {
|
|
vhost_virtqueue_stop(hdev,
|
|
vhost_virtqueue_stop(hdev,
|
|
vdev,
|
|
vdev,
|