aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/scsi_error.c15
-rw-r--r--drivers/scsi/scsi_transport_fc.c20
-rw-r--r--include/scsi/scsi.h1
-rw-r--r--include/scsi/scsi_transport_fc.h2
4 files changed, 27 insertions, 11 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index d45c69ca5737..33175974b55a 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -957,9 +957,10 @@ static int scsi_eh_abort_cmds(struct list_head *work_q,
957 "0x%p\n", current->comm, 957 "0x%p\n", current->comm,
958 scmd)); 958 scmd));
959 rtn = scsi_try_to_abort_cmd(scmd); 959 rtn = scsi_try_to_abort_cmd(scmd);
960 if (rtn == SUCCESS) { 960 if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
961 scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD; 961 scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD;
962 if (!scsi_device_online(scmd->device) || 962 if (!scsi_device_online(scmd->device) ||
963 rtn == FAST_IO_FAIL ||
963 !scsi_eh_tur(scmd)) { 964 !scsi_eh_tur(scmd)) {
964 scsi_eh_finish_cmd(scmd, done_q); 965 scsi_eh_finish_cmd(scmd, done_q);
965 } 966 }
@@ -1086,8 +1087,9 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
1086 " 0x%p\n", current->comm, 1087 " 0x%p\n", current->comm,
1087 sdev)); 1088 sdev));
1088 rtn = scsi_try_bus_device_reset(bdr_scmd); 1089 rtn = scsi_try_bus_device_reset(bdr_scmd);
1089 if (rtn == SUCCESS) { 1090 if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
1090 if (!scsi_device_online(sdev) || 1091 if (!scsi_device_online(sdev) ||
1092 rtn == FAST_IO_FAIL ||
1091 !scsi_eh_tur(bdr_scmd)) { 1093 !scsi_eh_tur(bdr_scmd)) {
1092 list_for_each_entry_safe(scmd, next, 1094 list_for_each_entry_safe(scmd, next,
1093 work_q, eh_entry) { 1095 work_q, eh_entry) {
@@ -1150,10 +1152,11 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
1150 "to target %d\n", 1152 "to target %d\n",
1151 current->comm, id)); 1153 current->comm, id));
1152 rtn = scsi_try_target_reset(tgtr_scmd); 1154 rtn = scsi_try_target_reset(tgtr_scmd);
1153 if (rtn == SUCCESS) { 1155 if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
1154 list_for_each_entry_safe(scmd, next, work_q, eh_entry) { 1156 list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
1155 if (id == scmd_id(scmd)) 1157 if (id == scmd_id(scmd))
1156 if (!scsi_device_online(scmd->device) || 1158 if (!scsi_device_online(scmd->device) ||
1159 rtn == FAST_IO_FAIL ||
1157 !scsi_eh_tur(tgtr_scmd)) 1160 !scsi_eh_tur(tgtr_scmd))
1158 scsi_eh_finish_cmd(scmd, 1161 scsi_eh_finish_cmd(scmd,
1159 done_q); 1162 done_q);
@@ -1209,10 +1212,11 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost,
1209 " %d\n", current->comm, 1212 " %d\n", current->comm,
1210 channel)); 1213 channel));
1211 rtn = scsi_try_bus_reset(chan_scmd); 1214 rtn = scsi_try_bus_reset(chan_scmd);
1212 if (rtn == SUCCESS) { 1215 if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
1213 list_for_each_entry_safe(scmd, next, work_q, eh_entry) { 1216 list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
1214 if (channel == scmd_channel(scmd)) 1217 if (channel == scmd_channel(scmd))
1215 if (!scsi_device_online(scmd->device) || 1218 if (!scsi_device_online(scmd->device) ||
1219 rtn == FAST_IO_FAIL ||
1216 !scsi_eh_tur(scmd)) 1220 !scsi_eh_tur(scmd))
1217 scsi_eh_finish_cmd(scmd, 1221 scsi_eh_finish_cmd(scmd,
1218 done_q); 1222 done_q);
@@ -1246,9 +1250,10 @@ static int scsi_eh_host_reset(struct list_head *work_q,
1246 , current->comm)); 1250 , current->comm));
1247 1251
1248 rtn = scsi_try_host_reset(scmd); 1252 rtn = scsi_try_host_reset(scmd);
1249 if (rtn == SUCCESS) { 1253 if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
1250 list_for_each_entry_safe(scmd, next, work_q, eh_entry) { 1254 list_for_each_entry_safe(scmd, next, work_q, eh_entry) {
1251 if (!scsi_device_online(scmd->device) || 1255 if (!scsi_device_online(scmd->device) ||
1256 rtn == FAST_IO_FAIL ||
1252 (!scsi_eh_try_stu(scmd) && !scsi_eh_tur(scmd)) || 1257 (!scsi_eh_try_stu(scmd) && !scsi_eh_tur(scmd)) ||
1253 !scsi_eh_tur(scmd)) 1258 !scsi_eh_tur(scmd))
1254 scsi_eh_finish_cmd(scmd, done_q); 1259 scsi_eh_finish_cmd(scmd, done_q);
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 55fe730a8606..06813789145c 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -3197,23 +3197,33 @@ fc_scsi_scan_rport(struct work_struct *work)
3197 * 3197 *
3198 * This routine can be called from a FC LLD scsi_eh callback. It 3198 * This routine can be called from a FC LLD scsi_eh callback. It
3199 * blocks the scsi_eh thread until the fc_rport leaves the 3199 * blocks the scsi_eh thread until the fc_rport leaves the
3200 * FC_PORTSTATE_BLOCKED. This is necessary to avoid the scsi_eh 3200 * FC_PORTSTATE_BLOCKED, or the fast_io_fail_tmo fires. This is
3201 * failing recovery actions for blocked rports which would lead to 3201 * necessary to avoid the scsi_eh failing recovery actions for blocked
3202 * offlined SCSI devices. 3202 * rports which would lead to offlined SCSI devices.
3203 *
3204 * Returns: 0 if the fc_rport left the state FC_PORTSTATE_BLOCKED.
3205 * FAST_IO_FAIL if the fast_io_fail_tmo fired, this should be
3206 * passed back to scsi_eh.
3203 */ 3207 */
3204void fc_block_scsi_eh(struct scsi_cmnd *cmnd) 3208int fc_block_scsi_eh(struct scsi_cmnd *cmnd)
3205{ 3209{
3206 struct Scsi_Host *shost = cmnd->device->host; 3210 struct Scsi_Host *shost = cmnd->device->host;
3207 struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); 3211 struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
3208 unsigned long flags; 3212 unsigned long flags;
3209 3213
3210 spin_lock_irqsave(shost->host_lock, flags); 3214 spin_lock_irqsave(shost->host_lock, flags);
3211 while (rport->port_state == FC_PORTSTATE_BLOCKED) { 3215 while (rport->port_state == FC_PORTSTATE_BLOCKED &&
3216 !(rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT)) {
3212 spin_unlock_irqrestore(shost->host_lock, flags); 3217 spin_unlock_irqrestore(shost->host_lock, flags);
3213 msleep(1000); 3218 msleep(1000);
3214 spin_lock_irqsave(shost->host_lock, flags); 3219 spin_lock_irqsave(shost->host_lock, flags);
3215 } 3220 }
3216 spin_unlock_irqrestore(shost->host_lock, flags); 3221 spin_unlock_irqrestore(shost->host_lock, flags);
3222
3223 if (rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT)
3224 return FAST_IO_FAIL;
3225
3226 return 0;
3217} 3227}
3218EXPORT_SYMBOL(fc_block_scsi_eh); 3228EXPORT_SYMBOL(fc_block_scsi_eh);
3219 3229
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 8b4deca996ad..832f41f37385 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -423,6 +423,7 @@ static inline int scsi_is_wlun(unsigned int lun)
423#define ADD_TO_MLQUEUE 0x2006 423#define ADD_TO_MLQUEUE 0x2006
424#define TIMEOUT_ERROR 0x2007 424#define TIMEOUT_ERROR 0x2007
425#define SCSI_RETURN_NOT_HANDLED 0x2008 425#define SCSI_RETURN_NOT_HANDLED 0x2008
426#define FAST_IO_FAIL 0x2009
426 427
427/* 428/*
428 * Midlevel queue return values. 429 * Midlevel queue return values.
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 8e86a94faf06..87d81b3ce564 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -807,6 +807,6 @@ void fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number,
807struct fc_vport *fc_vport_create(struct Scsi_Host *shost, int channel, 807struct fc_vport *fc_vport_create(struct Scsi_Host *shost, int channel,
808 struct fc_vport_identifiers *); 808 struct fc_vport_identifiers *);
809int fc_vport_terminate(struct fc_vport *vport); 809int fc_vport_terminate(struct fc_vport *vport);
810void fc_block_scsi_eh(struct scsi_cmnd *cmnd); 810int fc_block_scsi_eh(struct scsi_cmnd *cmnd);
811 811
812#endif /* SCSI_TRANSPORT_FC_H */ 812#endif /* SCSI_TRANSPORT_FC_H */