diff options
author | K. Y. Srinivasan <kys@microsoft.com> | 2012-04-05 15:26:52 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-04-25 04:51:43 -0400 |
commit | 42e22cac4e57f3e0b4b631c9489effe97f7d7d6c (patch) | |
tree | c5b2767d0b8c2ef2c6f043f387c10b293360376a /drivers/scsi/storvsc_drv.c | |
parent | c62eef0d1b592cfbe4793173e8af4098b13e4455 (diff) |
[SCSI] storvsc: Properly handle errors from the host
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>
Diffstat (limited to 'drivers/scsi/storvsc_drv.c')
-rw-r--r-- | drivers/scsi/storvsc_drv.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 83a1972a1999..528d52beaa1c 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c | |||
@@ -785,12 +785,22 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) | |||
785 | /* | 785 | /* |
786 | * If there is an error; offline the device since all | 786 | * If there is an error; offline the device since all |
787 | * error recovery strategies would have already been | 787 | * error recovery strategies would have already been |
788 | * deployed on the host side. | 788 | * deployed on the host side. However, if the command |
789 | * were a pass-through command deal with it appropriately. | ||
789 | */ | 790 | */ |
790 | if (vm_srb->srb_status == SRB_STATUS_ERROR) | 791 | scmnd->result = vm_srb->scsi_status; |
791 | scmnd->result = DID_TARGET_FAILURE << 16; | 792 | |
792 | else | 793 | if (vm_srb->srb_status == SRB_STATUS_ERROR) { |
793 | scmnd->result = vm_srb->scsi_status; | 794 | switch (scmnd->cmnd[0]) { |
795 | case ATA_16: | ||
796 | case ATA_12: | ||
797 | set_host_byte(scmnd, DID_PASSTHROUGH); | ||
798 | break; | ||
799 | default: | ||
800 | set_host_byte(scmnd, DID_TARGET_FAILURE); | ||
801 | } | ||
802 | } | ||
803 | |||
794 | 804 | ||
795 | /* | 805 | /* |
796 | * If the LUN is invalid; remove the device. | 806 | * If the LUN is invalid; remove the device. |