summaryrefslogtreecommitdiffstats
path: root/hw/scsi/scsi-bus.c
diff options
context:
space:
mode:
authorHannes Reinecke2021-02-24 19:14:50 +0100
committerPaolo Bonzini2021-03-06 11:42:57 +0100
commitf3126d65b393c015e8f87763fdccee99bb1119af (patch)
tree55e3593634cbaadde5e1a74f7c2d0e43c8001dd1 /hw/scsi/scsi-bus.c
parentscsi: inline sg_io_sense_from_errno() into the callers. (diff)
downloadqemu-f3126d65b393c015e8f87763fdccee99bb1119af.tar.gz
qemu-f3126d65b393c015e8f87763fdccee99bb1119af.tar.xz
qemu-f3126d65b393c015e8f87763fdccee99bb1119af.zip
scsi: move host_status handling into SCSI drivers
Some SCSI drivers like virtio have an internal mapping for the host_status. This patch moves the host_status translation into the SCSI drivers to allow those drivers to set up the correct values. Signed-off-by: Hannes Reinecke <hare@suse.de>. [Added default handling to avoid touching all drivers. - Paolo] Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw/scsi/scsi-bus.c')
-rw-r--r--hw/scsi/scsi-bus.c33
1 files changed, 31 insertions, 2 deletions
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index dc4141ec8d..2d674f94d7 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -692,6 +692,7 @@ SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
req->lun = lun;
req->hba_private = hba_private;
req->status = -1;
+ req->host_status = -1;
req->ops = reqops;
object_ref(OBJECT(d));
object_ref(OBJECT(qbus->parent));
@@ -1455,10 +1456,38 @@ void scsi_req_print(SCSIRequest *req)
}
}
+void scsi_req_complete_failed(SCSIRequest *req, int host_status)
+{
+ SCSISense sense;
+ int status;
+
+ assert(req->status == -1 && req->host_status == -1);
+ assert(req->ops != &reqops_unit_attention);
+
+ if (!req->bus->info->fail) {
+ status = scsi_sense_from_host_status(req->host_status, &sense);
+ if (status == CHECK_CONDITION) {
+ scsi_req_build_sense(req, sense);
+ }
+ scsi_req_complete(req, status);
+ return;
+ }
+
+ req->host_status = host_status;
+ scsi_req_ref(req);
+ scsi_req_dequeue(req);
+ req->bus->info->fail(req);
+
+ /* Cancelled requests might end up being completed instead of cancelled */
+ notifier_list_notify(&req->cancel_notifiers, req);
+ scsi_req_unref(req);
+}
+
void scsi_req_complete(SCSIRequest *req, int status)
{
- assert(req->status == -1);
+ assert(req->status == -1 && req->host_status == -1);
req->status = status;
+ req->host_status = SCSI_HOST_OK;
assert(req->sense_len <= sizeof(req->sense));
if (status == GOOD) {
@@ -1646,7 +1675,7 @@ static int put_scsi_requests(QEMUFile *f, void *pv, size_t size,
QTAILQ_FOREACH(req, &s->requests, next) {
assert(!req->io_canceled);
- assert(req->status == -1);
+ assert(req->status == -1 && req->host_status == -1);
assert(req->enqueued);
qemu_put_sbyte(f, req->retry ? 1 : 2);