diff options
author | Hannes Reinecke | 2021-02-24 19:14:50 +0100 |
---|---|---|
committer | Paolo Bonzini | 2021-03-06 11:42:57 +0100 |
commit | f3126d65b393c015e8f87763fdccee99bb1119af (patch) | |
tree | 55e3593634cbaadde5e1a74f7c2d0e43c8001dd1 /hw/scsi/scsi-bus.c | |
parent | scsi: inline sg_io_sense_from_errno() into the callers. (diff) | |
download | qemu-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.c | 33 |
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); |