diff options
author | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-03-09 01:24:17 +0100 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-06-05 16:23:45 +0200 |
commit | 427e59f09fdba387547106de7bab980b7fff77be (patch) | |
tree | 4701ebff8882da0f5ff15f1dab3468d259b2c5dd /drivers/scsi/scsi.c | |
parent | [SCSI] SCSI: remove dev->power.power_state from mesh driver (diff) | |
download | linux-427e59f09fdba387547106de7bab980b7fff77be.tar.xz linux-427e59f09fdba387547106de7bab980b7fff77be.zip |
[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.c | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 110e776d1a07..36c92f961e15 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); } |