[SCSI] make use of the residue value
authorJames Bottomley <James.Bottomley@HansenPartnership.com>
Sun, 9 Mar 2008 00:24:17 +0000 (18:24 -0600)
committerJames Bottomley <James.Bottomley@HansenPartnership.com>
Thu, 5 Jun 2008 14:23:45 +0000 (09:23 -0500)
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>
drivers/scsi/scsi.c

index 110e776d1a078cbd24cfdb795f7fec16cf95f1c3..36c92f961e154fb46b94690b36dd09d624e59666 100644 (file)
@@ -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);
 }