diff options
Diffstat (limited to 'drivers/scsi/scsi_error.c')
-rw-r--r-- | drivers/scsi/scsi_error.c | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index bfa569facd5b..1c470e31ae81 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -1055,7 +1055,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, | |||
1055 | struct scsi_device *sdev = scmd->device; | 1055 | struct scsi_device *sdev = scmd->device; |
1056 | struct Scsi_Host *shost = sdev->host; | 1056 | struct Scsi_Host *shost = sdev->host; |
1057 | DECLARE_COMPLETION_ONSTACK(done); | 1057 | DECLARE_COMPLETION_ONSTACK(done); |
1058 | unsigned long timeleft = timeout; | 1058 | unsigned long timeleft = timeout, delay; |
1059 | struct scsi_eh_save ses; | 1059 | struct scsi_eh_save ses; |
1060 | const unsigned long stall_for = msecs_to_jiffies(100); | 1060 | const unsigned long stall_for = msecs_to_jiffies(100); |
1061 | int rtn; | 1061 | int rtn; |
@@ -1066,7 +1066,29 @@ retry: | |||
1066 | 1066 | ||
1067 | scsi_log_send(scmd); | 1067 | scsi_log_send(scmd); |
1068 | scmd->scsi_done = scsi_eh_done; | 1068 | scmd->scsi_done = scsi_eh_done; |
1069 | rtn = shost->hostt->queuecommand(shost, scmd); | 1069 | |
1070 | /* | ||
1071 | * Lock sdev->state_mutex to avoid that scsi_device_quiesce() can | ||
1072 | * change the SCSI device state after we have examined it and before | ||
1073 | * .queuecommand() is called. | ||
1074 | */ | ||
1075 | mutex_lock(&sdev->state_mutex); | ||
1076 | while (sdev->sdev_state == SDEV_BLOCK && timeleft > 0) { | ||
1077 | mutex_unlock(&sdev->state_mutex); | ||
1078 | SCSI_LOG_ERROR_RECOVERY(5, sdev_printk(KERN_DEBUG, sdev, | ||
1079 | "%s: state %d <> %d\n", __func__, sdev->sdev_state, | ||
1080 | SDEV_BLOCK)); | ||
1081 | delay = min(timeleft, stall_for); | ||
1082 | timeleft -= delay; | ||
1083 | msleep(jiffies_to_msecs(delay)); | ||
1084 | mutex_lock(&sdev->state_mutex); | ||
1085 | } | ||
1086 | if (sdev->sdev_state != SDEV_BLOCK) | ||
1087 | rtn = shost->hostt->queuecommand(shost, scmd); | ||
1088 | else | ||
1089 | rtn = SCSI_MLQUEUE_DEVICE_BUSY; | ||
1090 | mutex_unlock(&sdev->state_mutex); | ||
1091 | |||
1070 | if (rtn) { | 1092 | if (rtn) { |
1071 | if (timeleft > stall_for) { | 1093 | if (timeleft > stall_for) { |
1072 | scsi_eh_restore_cmnd(scmd, &ses); | 1094 | scsi_eh_restore_cmnd(scmd, &ses); |