diff options
Diffstat (limited to 'drivers/scsi/scsi_error.c')
| -rw-r--r-- | drivers/scsi/scsi_error.c | 44 |
1 files changed, 42 insertions, 2 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 2768bf6ffe5..bbbc186dbc1 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -307,7 +307,33 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) (sshdr.asc == 0x04) && (sshdr.ascq == 0x02)) return FAILED; - return NEEDS_RETRY; + 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 + */ + return NEEDS_RETRY; + else + /* + * for normal (non barrier) commands, pass the + * UA upwards for a determination in the + * completion functions + */ + return SUCCESS; + /* these three are not supported */ case COPY_ABORTED: case VOLUME_OVERFLOW: @@ -1751,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 @@ -1764,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); @@ -1861,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; @@ -1923,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); |