summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi.c
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@HansenPartnership.com>2008-03-08 18:24:17 -0600
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-06-05 09:23:45 -0500
commit427e59f09fdba387547106de7bab980b7fff77be (patch)
tree4701ebff8882da0f5ff15f1dab3468d259b2c5dd /drivers/scsi/scsi.c
parent19c4158bcdf42ee3b2394342caf14f8471d2c78e (diff)
[SCSI] make use of the residue value
USB sometimes doesn't return an error but instead returns a residue value indicating part (or all) of the command wasn't completed. So if the driver _done() error processing indicates the command was fully processed, subtract off the residue so that this USB error gets propagated. Cc: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/scsi.c')
-rw-r--r--drivers/scsi/scsi.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 110e776d1a0..36c92f961e1 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -855,9 +855,18 @@ void scsi_finish_command(struct scsi_cmnd *cmd)
good_bytes = scsi_bufflen(cmd);
if (cmd->request->cmd_type != REQ_TYPE_BLOCK_PC) {
+ int old_good_bytes = good_bytes;
drv = scsi_cmd_to_driver(cmd);
if (drv->done)
good_bytes = drv->done(cmd);
+ /*
+ * USB may not give sense identifying bad sector and
+ * simply return a residue instead, so subtract off the
+ * residue if drv->done() error processing indicates no
+ * change to the completion length.
+ */
+ if (good_bytes == old_good_bytes)
+ good_bytes -= scsi_get_resid(cmd);
}
scsi_io_completion(cmd, good_bytes);
}