Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
[deliverable/linux.git] / drivers / scsi / scsi_error.c
index 45c75649b9e083e489e1a935a2617a8d0461749f..991de3c15cfcbc4bcc61096272e747f40e30448c 100644 (file)
@@ -223,7 +223,7 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost,
  * @scmd:      Cmd to have sense checked.
  *
  * Return value:
- *     SUCCESS or FAILED or NEEDS_RETRY
+ *     SUCCESS or FAILED or NEEDS_RETRY or TARGET_ERROR
  *
  * Notes:
  *     When a deferred error is detected the current command has
@@ -326,17 +326,19 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
                 */
                return SUCCESS;
 
-               /* these three are not supported */
+               /* these are not supported */
        case COPY_ABORTED:
        case VOLUME_OVERFLOW:
        case MISCOMPARE:
-               return SUCCESS;
+       case BLANK_CHECK:
+       case DATA_PROTECT:
+               return TARGET_ERROR;
 
        case MEDIUM_ERROR:
                if (sshdr.asc == 0x11 || /* UNRECOVERED READ ERR */
                    sshdr.asc == 0x13 || /* AMNF DATA FIELD */
                    sshdr.asc == 0x14) { /* RECORD NOT FOUND */
-                       return SUCCESS;
+                       return TARGET_ERROR;
                }
                return NEEDS_RETRY;
 
@@ -344,11 +346,9 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
                if (scmd->device->retry_hwerror)
                        return ADD_TO_MLQUEUE;
                else
-                       return SUCCESS;
+                       return TARGET_ERROR;
 
        case ILLEGAL_REQUEST:
-       case BLANK_CHECK:
-       case DATA_PROTECT:
        default:
                return SUCCESS;
        }
@@ -787,6 +787,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
                case SUCCESS:
                case NEEDS_RETRY:
                case FAILED:
+               case TARGET_ERROR:
                        break;
                case ADD_TO_MLQUEUE:
                        rtn = NEEDS_RETRY;
@@ -1469,6 +1470,14 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
                rtn = scsi_check_sense(scmd);
                if (rtn == NEEDS_RETRY)
                        goto maybe_retry;
+               else if (rtn == TARGET_ERROR) {
+                       /*
+                        * Need to modify host byte to signal a
+                        * permanent target failure
+                        */
+                       scmd->result |= (DID_TARGET_FAILURE << 16);
+                       rtn = SUCCESS;
+               }
                /* if rtn == FAILED, we have no sense information;
                 * returning FAILED will wake the error handler thread
                 * to collect the sense and redo the decide
@@ -1486,6 +1495,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
        case RESERVATION_CONFLICT:
                sdev_printk(KERN_INFO, scmd->device,
                            "reservation conflict\n");
+               scmd->result |= (DID_NEXUS_FAILURE << 16);
                return SUCCESS; /* causes immediate i/o error */
        default:
                return FAILED;
This page took 0.024729 seconds and 5 git commands to generate.