[SCSI] storvsc: Properly handle errors from the host
authorK. Y. Srinivasan <kys@microsoft.com>
Thu, 5 Apr 2012 19:26:52 +0000 (12:26 -0700)
committerJames Bottomley <JBottomley@Parallels.com>
Wed, 25 Apr 2012 08:51:43 +0000 (09:51 +0100)
Hyper-V cannot process some commands like ATA_12 and ATA_16. It also returns a
very generic error when this happens (SRB_STATUS_ERROR).  Most of the time we
treat SRB_STATUS_ERROR as DID_TARGET_FAILURE which causes error handler retry,
but in the case of pass through commands, they'll never succeed (and the error
handler will offline the device), so put a discriminating block in the command
completion routing and send the SRB_STATUS_ERROR upwards with DID_PASSTHROUGH
for commands we know should not be retried.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/storvsc_drv.c

index 83a1972a1999b816dc287766c6a71c9f557bcedb..528d52beaa1ca67b44079438aa3c87408b24c883 100644 (file)
@@ -785,12 +785,22 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
        /*
         * If there is an error; offline the device since all
         * error recovery strategies would have already been
-        * deployed on the host side.
+        * deployed on the host side. However, if the command
+        * were a pass-through command deal with it appropriately.
         */
-       if (vm_srb->srb_status == SRB_STATUS_ERROR)
-               scmnd->result = DID_TARGET_FAILURE << 16;
-       else
-               scmnd->result = vm_srb->scsi_status;
+       scmnd->result = vm_srb->scsi_status;
+
+       if (vm_srb->srb_status == SRB_STATUS_ERROR) {
+               switch (scmnd->cmnd[0]) {
+               case ATA_16:
+               case ATA_12:
+                       set_host_byte(scmnd, DID_PASSTHROUGH);
+                       break;
+               default:
+                       set_host_byte(scmnd, DID_TARGET_FAILURE);
+               }
+       }
+
 
        /*
         * If the LUN is invalid; remove the device.