aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r--drivers/scsi/scsi_lib.c36
1 files changed, 34 insertions, 2 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index bf80a4c5a48..6d5c7ff43f5 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -667,6 +667,30 @@ void scsi_release_buffers(struct scsi_cmnd *cmd)
667} 667}
668EXPORT_SYMBOL(scsi_release_buffers); 668EXPORT_SYMBOL(scsi_release_buffers);
669 669
670static int __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result)
671{
672 int error = 0;
673
674 switch(host_byte(result)) {
675 case DID_TRANSPORT_FAILFAST:
676 error = -ENOLINK;
677 break;
678 case DID_TARGET_FAILURE:
679 cmd->result |= (DID_OK << 16);
680 error = -EREMOTEIO;
681 break;
682 case DID_NEXUS_FAILURE:
683 cmd->result |= (DID_OK << 16);
684 error = -EBADE;
685 break;
686 default:
687 error = -EIO;
688 break;
689 }
690
691 return error;
692}
693
670/* 694/*
671 * Function: scsi_io_completion() 695 * Function: scsi_io_completion()
672 * 696 *
@@ -737,7 +761,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
737 req->sense_len = len; 761 req->sense_len = len;
738 } 762 }
739 if (!sense_deferred) 763 if (!sense_deferred)
740 error = -EIO; 764 error = __scsi_error_from_host_byte(cmd, result);
741 } 765 }
742 766
743 req->resid_len = scsi_get_resid(cmd); 767 req->resid_len = scsi_get_resid(cmd);
@@ -796,7 +820,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
796 if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL) 820 if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL)
797 return; 821 return;
798 822
799 error = -EIO; 823 error = __scsi_error_from_host_byte(cmd, result);
800 824
801 if (host_byte(result) == DID_RESET) { 825 if (host_byte(result) == DID_RESET) {
802 /* Third party bus reset or reset for error recovery 826 /* Third party bus reset or reset for error recovery
@@ -843,6 +867,13 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
843 description = "Host Data Integrity Failure"; 867 description = "Host Data Integrity Failure";
844 action = ACTION_FAIL; 868 action = ACTION_FAIL;
845 error = -EILSEQ; 869 error = -EILSEQ;
870 /* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
871 } else if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) &&
872 (cmd->cmnd[0] == UNMAP ||
873 cmd->cmnd[0] == WRITE_SAME_16 ||
874 cmd->cmnd[0] == WRITE_SAME)) {
875 description = "Discard failure";
876 action = ACTION_FAIL;
846 } else 877 } else
847 action = ACTION_FAIL; 878 action = ACTION_FAIL;
848 break; 879 break;
@@ -1038,6 +1069,7 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev,
1038 cmd->request = req; 1069 cmd->request = req;
1039 1070
1040 cmd->cmnd = req->cmd; 1071 cmd->cmnd = req->cmd;
1072 cmd->prot_op = SCSI_PROT_NORMAL;
1041 1073
1042 return cmd; 1074 return cmd;
1043} 1075}