aboutsummaryrefslogtreecommitdiff
path: root/hw/scsi/virtio-scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/scsi/virtio-scsi.c')
-rw-r--r--hw/scsi/virtio-scsi.c36
1 files changed, 21 insertions, 15 deletions
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 34bba35d83..204e14f237 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -592,26 +592,32 @@ static void virtio_scsi_handle_cmd_req_submit(VirtIOSCSI *s, VirtIOSCSIReq *req)
void virtio_scsi_handle_cmd_vq(VirtIOSCSI *s, VirtQueue *vq)
{
VirtIOSCSIReq *req, *next;
- int ret;
+ int ret = 0;
QTAILQ_HEAD(, VirtIOSCSIReq) reqs = QTAILQ_HEAD_INITIALIZER(reqs);
- while ((req = virtio_scsi_pop_req(s, vq))) {
- ret = virtio_scsi_handle_cmd_req_prepare(s, req);
- if (!ret) {
- QTAILQ_INSERT_TAIL(&reqs, req, next);
- } else if (ret == -EINVAL) {
- /* The device is broken and shouldn't process any request */
- while (!QTAILQ_EMPTY(&reqs)) {
- req = QTAILQ_FIRST(&reqs);
- QTAILQ_REMOVE(&reqs, req, next);
- blk_io_unplug(req->sreq->dev->conf.blk);
- scsi_req_unref(req->sreq);
- virtqueue_detach_element(req->vq, &req->elem, 0);
- virtio_scsi_free_req(req);
+ do {
+ virtio_queue_set_notification(vq, 0);
+
+ while ((req = virtio_scsi_pop_req(s, vq))) {
+ ret = virtio_scsi_handle_cmd_req_prepare(s, req);
+ if (!ret) {
+ QTAILQ_INSERT_TAIL(&reqs, req, next);
+ } else if (ret == -EINVAL) {
+ /* The device is broken and shouldn't process any request */
+ while (!QTAILQ_EMPTY(&reqs)) {
+ req = QTAILQ_FIRST(&reqs);
+ QTAILQ_REMOVE(&reqs, req, next);
+ blk_io_unplug(req->sreq->dev->conf.blk);
+ scsi_req_unref(req->sreq);
+ virtqueue_detach_element(req->vq, &req->elem, 0);
+ virtio_scsi_free_req(req);
+ }
}
}
- }
+
+ virtio_queue_set_notification(vq, 1);
+ } while (ret != -EINVAL && !virtio_queue_empty(vq));
QTAILQ_FOREACH_SAFE(req, &reqs, next, next) {
virtio_scsi_handle_cmd_req_submit(s, req);