Merge branch 'for-linus' of git://neil.brown.name/md
[sfrench/cifs-2.6.git] / drivers / scsi / scsi_error.c
index a5d630f5f5199e84a9e236a2862a89573f98d7a5..bbbc186dbc1a413f0ef0e77c07710fa11bfb03e6 100644 (file)
@@ -307,7 +307,20 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
                    (sshdr.asc == 0x04) && (sshdr.ascq == 0x02))
                        return FAILED;
 
-               if (blk_barrier_rq(scmd->request))
+               if (sshdr.asc == 0x3f && sshdr.ascq == 0x0e)
+                       scmd_printk(KERN_WARNING, scmd,
+                                   "Warning! Received an indication that the "
+                                   "LUN assignments on this target have "
+                                   "changed. The Linux SCSI layer does not "
+                                   "automatically remap LUN assignments.\n");
+               else if (sshdr.asc == 0x3f)
+                       scmd_printk(KERN_WARNING, scmd,
+                                   "Warning! Received an indication that the "
+                                   "operating parameters on this target have "
+                                   "changed. The Linux SCSI layer does not "
+                                   "automatically adjust these parameters.\n");
+
+               if (scmd->request->cmd_flags & REQ_HARDBARRIER)
                        /*
                         * barrier requests should always retry on UA
                         * otherwise block will get a spurious error
@@ -1318,16 +1331,16 @@ int scsi_noretry_cmd(struct scsi_cmnd *scmd)
        case DID_OK:
                break;
        case DID_BUS_BUSY:
-               return blk_failfast_transport(scmd->request);
+               return (scmd->request->cmd_flags & REQ_FAILFAST_TRANSPORT);
        case DID_PARITY:
-               return blk_failfast_dev(scmd->request);
+               return (scmd->request->cmd_flags & REQ_FAILFAST_DEV);
        case DID_ERROR:
                if (msg_byte(scmd->result) == COMMAND_COMPLETE &&
                    status_byte(scmd->result) == RESERVATION_CONFLICT)
                        return 0;
                /* fall through */
        case DID_SOFT_ERROR:
-               return blk_failfast_driver(scmd->request);
+               return (scmd->request->cmd_flags & REQ_FAILFAST_DRIVER);
        }
 
        switch (status_byte(scmd->result)) {
@@ -1336,7 +1349,9 @@ int scsi_noretry_cmd(struct scsi_cmnd *scmd)
                 * assume caller has checked sense and determinted
                 * the check condition was retryable.
                 */
-               return blk_failfast_dev(scmd->request);
+               if (scmd->request->cmd_flags & REQ_FAILFAST_DEV ||
+                   scmd->request->cmd_type == REQ_TYPE_BLOCK_PC)
+                       return 1;
        }
 
        return 0;
@@ -1762,6 +1777,14 @@ int scsi_error_handler(void *data)
                 * what we need to do to get it up and online again (if we can).
                 * If we fail, we end up taking the thing offline.
                 */
+               if (scsi_autopm_get_host(shost) != 0) {
+                       SCSI_LOG_ERROR_RECOVERY(1,
+                               printk(KERN_ERR "Error handler scsi_eh_%d "
+                                               "unable to autoresume\n",
+                                               shost->host_no));
+                       continue;
+               }
+
                if (shost->transportt->eh_strategy_handler)
                        shost->transportt->eh_strategy_handler(shost);
                else
@@ -1775,6 +1798,7 @@ int scsi_error_handler(void *data)
                 * which are still online.
                 */
                scsi_restart_operations(shost);
+               scsi_autopm_put_host(shost);
                set_current_state(TASK_INTERRUPTIBLE);
        }
        __set_current_state(TASK_RUNNING);
@@ -1872,12 +1896,16 @@ scsi_reset_provider_done_command(struct scsi_cmnd *scmd)
 int
 scsi_reset_provider(struct scsi_device *dev, int flag)
 {
-       struct scsi_cmnd *scmd = scsi_get_command(dev, GFP_KERNEL);
+       struct scsi_cmnd *scmd;
        struct Scsi_Host *shost = dev->host;
        struct request req;
        unsigned long flags;
        int rtn;
 
+       if (scsi_autopm_get_host(shost) < 0)
+               return FAILED;
+
+       scmd = scsi_get_command(dev, GFP_KERNEL);
        blk_rq_init(NULL, &req);
        scmd->request = &req;
 
@@ -1934,6 +1962,7 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
        scsi_run_host_queues(shost);
 
        scsi_next_command(scmd);
+       scsi_autopm_put_host(shost);
        return rtn;
 }
 EXPORT_SYMBOL(scsi_reset_provider);