aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_transport_fc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/scsi_transport_fc.c')
-rw-r--r--drivers/scsi/scsi_transport_fc.c46
1 files changed, 40 insertions, 6 deletions
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 13ea64119b73..8db656214b5c 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -31,6 +31,7 @@
31#include <scsi/scsi_host.h> 31#include <scsi/scsi_host.h>
32#include <scsi/scsi_transport.h> 32#include <scsi/scsi_transport.h>
33#include <scsi/scsi_transport_fc.h> 33#include <scsi/scsi_transport_fc.h>
34#include <scsi/scsi_cmnd.h>
34#include "scsi_priv.h" 35#include "scsi_priv.h"
35 36
36/* 37/*
@@ -1090,6 +1091,40 @@ static int fc_rport_match(struct attribute_container *cont,
1090} 1091}
1091 1092
1092 1093
1094/**
1095 * fc_timed_out - FC Transport I/O timeout intercept handler
1096 *
1097 * @scmd: The SCSI command which timed out
1098 *
1099 * This routine protects against error handlers getting invoked while a
1100 * rport is in a blocked state, typically due to a temporarily loss of
1101 * connectivity. If the error handlers are allowed to proceed, requests
1102 * to abort i/o, reset the target, etc will likely fail as there is no way
1103 * to communicate with the device to perform the requested function. These
1104 * failures may result in the midlayer taking the device offline, requiring
1105 * manual intervention to restore operation.
1106 *
1107 * This routine, called whenever an i/o times out, validates the state of
1108 * the underlying rport. If the rport is blocked, it returns
1109 * EH_RESET_TIMER, which will continue to reschedule the timeout.
1110 * Eventually, either the device will return, or devloss_tmo will fire,
1111 * and when the timeout then fires, it will be handled normally.
1112 * If the rport is not blocked, normal error handling continues.
1113 *
1114 * Notes:
1115 * This routine assumes no locks are held on entry.
1116 **/
1117static enum scsi_eh_timer_return
1118fc_timed_out(struct scsi_cmnd *scmd)
1119{
1120 struct fc_rport *rport = starget_to_rport(scsi_target(scmd->device));
1121
1122 if (rport->port_state == FC_PORTSTATE_BLOCKED)
1123 return EH_RESET_TIMER;
1124
1125 return EH_NOT_HANDLED;
1126}
1127
1093/* 1128/*
1094 * Must be called with shost->host_lock held 1129 * Must be called with shost->host_lock held
1095 */ 1130 */
@@ -1115,15 +1150,13 @@ static int fc_user_scan(struct Scsi_Host *shost, uint channel,
1115struct scsi_transport_template * 1150struct scsi_transport_template *
1116fc_attach_transport(struct fc_function_template *ft) 1151fc_attach_transport(struct fc_function_template *ft)
1117{ 1152{
1118 struct fc_internal *i = kmalloc(sizeof(struct fc_internal),
1119 GFP_KERNEL);
1120 int count; 1153 int count;
1154 struct fc_internal *i = kzalloc(sizeof(struct fc_internal),
1155 GFP_KERNEL);
1121 1156
1122 if (unlikely(!i)) 1157 if (unlikely(!i))
1123 return NULL; 1158 return NULL;
1124 1159
1125 memset(i, 0, sizeof(struct fc_internal));
1126
1127 i->t.target_attrs.ac.attrs = &i->starget_attrs[0]; 1160 i->t.target_attrs.ac.attrs = &i->starget_attrs[0];
1128 i->t.target_attrs.ac.class = &fc_transport_class.class; 1161 i->t.target_attrs.ac.class = &fc_transport_class.class;
1129 i->t.target_attrs.ac.match = fc_target_match; 1162 i->t.target_attrs.ac.match = fc_target_match;
@@ -1148,6 +1181,8 @@ fc_attach_transport(struct fc_function_template *ft)
1148 /* Transport uses the shost workq for scsi scanning */ 1181 /* Transport uses the shost workq for scsi scanning */
1149 i->t.create_work_queue = 1; 1182 i->t.create_work_queue = 1;
1150 1183
1184 i->t.eh_timed_out = fc_timed_out;
1185
1151 i->t.user_scan = fc_user_scan; 1186 i->t.user_scan = fc_user_scan;
1152 1187
1153 /* 1188 /*
@@ -1305,12 +1340,11 @@ fc_rport_create(struct Scsi_Host *shost, int channel,
1305 size_t size; 1340 size_t size;
1306 1341
1307 size = (sizeof(struct fc_rport) + fci->f->dd_fcrport_size); 1342 size = (sizeof(struct fc_rport) + fci->f->dd_fcrport_size);
1308 rport = kmalloc(size, GFP_KERNEL); 1343 rport = kzalloc(size, GFP_KERNEL);
1309 if (unlikely(!rport)) { 1344 if (unlikely(!rport)) {
1310 printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__); 1345 printk(KERN_ERR "%s: allocation failure\n", __FUNCTION__);
1311 return NULL; 1346 return NULL;
1312 } 1347 }
1313 memset(rport, 0, size);
1314 1348
1315 rport->maxframe_size = -1; 1349 rport->maxframe_size = -1;
1316 rport->supported_classes = FC_COS_UNSPECIFIED; 1350 rport->supported_classes = FC_COS_UNSPECIFIED;