aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/scsi/virtio-scsi.c42
1 files changed, 27 insertions, 15 deletions
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 34a968ecfb..417fbc71d6 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -472,16 +472,32 @@ bool virtio_scsi_handle_ctrl_vq(VirtIOSCSI *s, VirtQueue *vq)
return progress;
}
+/*
+ * If dataplane is configured but not yet started, do so now and return true on
+ * success.
+ *
+ * Dataplane is started by the core virtio code but virtqueue handler functions
+ * can also be invoked when a guest kicks before DRIVER_OK, so this helper
+ * function helps us deal with manually starting ioeventfd in that case.
+ */
+static bool virtio_scsi_defer_to_dataplane(VirtIOSCSI *s)
+{
+ if (!s->ctx || s->dataplane_started) {
+ return false;
+ }
+
+ virtio_device_start_ioeventfd(&s->parent_obj.parent_obj);
+ return !s->dataplane_fenced;
+}
+
static void virtio_scsi_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
{
VirtIOSCSI *s = (VirtIOSCSI *)vdev;
- if (s->ctx) {
- virtio_device_start_ioeventfd(vdev);
- if (!s->dataplane_fenced) {
- return;
- }
+ if (virtio_scsi_defer_to_dataplane(s)) {
+ return;
}
+
virtio_scsi_acquire(s);
virtio_scsi_handle_ctrl_vq(s, vq);
virtio_scsi_release(s);
@@ -720,12 +736,10 @@ static void virtio_scsi_handle_cmd(VirtIODevice *vdev, VirtQueue *vq)
/* use non-QOM casts in the data path */
VirtIOSCSI *s = (VirtIOSCSI *)vdev;
- if (s->ctx && !s->dataplane_started) {
- virtio_device_start_ioeventfd(vdev);
- if (!s->dataplane_fenced) {
- return;
- }
+ if (virtio_scsi_defer_to_dataplane(s)) {
+ return;
}
+
virtio_scsi_acquire(s);
virtio_scsi_handle_cmd_vq(s, vq);
virtio_scsi_release(s);
@@ -855,12 +869,10 @@ static void virtio_scsi_handle_event(VirtIODevice *vdev, VirtQueue *vq)
{
VirtIOSCSI *s = VIRTIO_SCSI(vdev);
- if (s->ctx) {
- virtio_device_start_ioeventfd(vdev);
- if (!s->dataplane_fenced) {
- return;
- }
+ if (virtio_scsi_defer_to_dataplane(s)) {
+ return;
}
+
virtio_scsi_acquire(s);
virtio_scsi_handle_event_vq(s, vq);
virtio_scsi_release(s);