From 4f93181d999141d8d87427d7ec0be1be1e21e868 Mon Sep 17 00:00:00 2001 From: mikeb Date: Wed, 21 Jun 2017 18:18:08 +0000 Subject: [PATCH] Don't confuse SCSI command status and transfer error code. While here, make SCSI command completion routine more robust. --- sys/dev/pv/hvs.c | 56 ++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/sys/dev/pv/hvs.c b/sys/dev/pv/hvs.c index a0f08c8ab12..5acac166ea4 100644 --- a/sys/dev/pv/hvs.c +++ b/sys/dev/pv/hvs.c @@ -614,31 +614,41 @@ hvs_scsi_cmd_done(struct hvs_ccb *ccb) xs = ccb->ccb_xfer; srb = &cmd->io.cmd_srb; - if (srb->srb_datalen > xs->datalen) - printf("%s: transfer length %u too large: %u\n", - sc->sc_dev.dv_xname, srb->srb_datalen, xs->datalen); - else if (srb->srb_datalen) - xs->resid = xs->datalen - srb->srb_datalen; - - if ((srb->srb_scsistatus & 0xff) == SCSI_CHECK && - srb->srb_iostatus & SRB_STATUS_AUTOSENSE_VALID) - memcpy(&xs->sense, srb->srb_data, MIN(sizeof(xs->sense), - srb->srb_senselen)); - - error = srb->srb_scsistatus & 0xff; - - if (srb->srb_scsistatus != SCSI_OK) { - KERNEL_LOCK(); - hvs_scsi_done(xs, error); - KERNEL_UNLOCK(); - return; + xs->status = srb->srb_scsistatus & 0xff; + + switch (xs->status) { + case SCSI_OK: + if ((srb->srb_iostatus & ~(SRB_STATUS_AUTOSENSE_VALID | + SRB_STATUS_QUEUE_FROZEN)) != SRB_STATUS_SUCCESS) + error = XS_SELTIMEOUT; + else + error = XS_NOERROR; + break; + case SCSI_BUSY: + case SCSI_QUEUE_FULL: + printf("%s: status %#x iostatus %#x (busy)\n", + sc->sc_dev.dv_xname, srb->srb_scsistatus, + srb->srb_iostatus); + xs->error = XS_BUSY; + break; + case SCSI_CHECK: + if (srb->srb_iostatus & SRB_STATUS_AUTOSENSE_VALID) { + memcpy(&xs->sense, srb->srb_data, + MIN(sizeof(xs->sense), srb->srb_senselen)); + error = XS_SENSE; + break; + } + /* FALLTHROUGH */ + default: + error = XS_DRIVER_STUFFUP; } - if ((srb->srb_iostatus & ~(SRB_STATUS_AUTOSENSE_VALID | - SRB_STATUS_QUEUE_FROZEN)) != SRB_STATUS_SUCCESS) - error = XS_SELTIMEOUT; - else if (xs->cmd->opcode == INQUIRY) - fixup_inquiry(xs, srb); + if (error == XS_NOERROR) { + if (xs->cmd->opcode == INQUIRY) + fixup_inquiry(xs, srb); + else if (srb->srb_direction != SRB_DATA_NONE) + xs->resid = xs->datalen - srb->srb_datalen; + } KERNEL_LOCK(); hvs_scsi_done(xs, error); -- 2.20.1