aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_io.c106
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_tgt.c11
2 files changed, 70 insertions, 47 deletions
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c
index e897ce975bb8..43258c3c90ae 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_io.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_io.c
@@ -1089,6 +1089,48 @@ int bnx2fc_eh_device_reset(struct scsi_cmnd *sc_cmd)
1089 return bnx2fc_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET); 1089 return bnx2fc_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET);
1090} 1090}
1091 1091
1092int bnx2fc_expl_logo(struct fc_lport *lport, struct bnx2fc_cmd *io_req)
1093{
1094 struct bnx2fc_rport *tgt = io_req->tgt;
1095 struct fc_rport_priv *rdata = tgt->rdata;
1096 int logo_issued;
1097 int rc = SUCCESS;
1098 int wait_cnt = 0;
1099
1100 BNX2FC_IO_DBG(io_req, "Expl logo - tgt flags = 0x%lx\n",
1101 tgt->flags);
1102 logo_issued = test_and_set_bit(BNX2FC_FLAG_EXPL_LOGO,
1103 &tgt->flags);
1104 io_req->wait_for_comp = 1;
1105 bnx2fc_initiate_cleanup(io_req);
1106
1107 spin_unlock_bh(&tgt->tgt_lock);
1108
1109 wait_for_completion(&io_req->tm_done);
1110
1111 io_req->wait_for_comp = 0;
1112 /*
1113 * release the reference taken in eh_abort to allow the
1114 * target to re-login after flushing IOs
1115 */
1116 kref_put(&io_req->refcount, bnx2fc_cmd_release);
1117
1118 if (!logo_issued) {
1119 clear_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags);
1120 mutex_lock(&lport->disc.disc_mutex);
1121 lport->tt.rport_logoff(rdata);
1122 mutex_unlock(&lport->disc.disc_mutex);
1123 do {
1124 msleep(BNX2FC_RELOGIN_WAIT_TIME);
1125 if (wait_cnt++ > BNX2FC_RELOGIN_WAIT_CNT) {
1126 rc = FAILED;
1127 break;
1128 }
1129 } while (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags));
1130 }
1131 spin_lock_bh(&tgt->tgt_lock);
1132 return rc;
1133}
1092/** 1134/**
1093 * bnx2fc_eh_abort - eh_abort_handler api to abort an outstanding 1135 * bnx2fc_eh_abort - eh_abort_handler api to abort an outstanding
1094 * SCSI command 1136 * SCSI command
@@ -1103,10 +1145,7 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
1103 struct fc_rport_libfc_priv *rp = rport->dd_data; 1145 struct fc_rport_libfc_priv *rp = rport->dd_data;
1104 struct bnx2fc_cmd *io_req; 1146 struct bnx2fc_cmd *io_req;
1105 struct fc_lport *lport; 1147 struct fc_lport *lport;
1106 struct fc_rport_priv *rdata;
1107 struct bnx2fc_rport *tgt; 1148 struct bnx2fc_rport *tgt;
1108 int logo_issued;
1109 int wait_cnt = 0;
1110 int rc = FAILED; 1149 int rc = FAILED;
1111 1150
1112 1151
@@ -1183,58 +1222,31 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
1183 list_add_tail(&io_req->link, &tgt->io_retire_queue); 1222 list_add_tail(&io_req->link, &tgt->io_retire_queue);
1184 1223
1185 init_completion(&io_req->tm_done); 1224 init_completion(&io_req->tm_done);
1186 io_req->wait_for_comp = 1;
1187 1225
1188 if (!test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS, &io_req->req_flags)) { 1226 if (test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS, &io_req->req_flags)) {
1189 /* Cancel the current timer running on this io_req */
1190 if (cancel_delayed_work(&io_req->timeout_work))
1191 kref_put(&io_req->refcount,
1192 bnx2fc_cmd_release); /* drop timer hold */
1193 set_bit(BNX2FC_FLAG_EH_ABORT, &io_req->req_flags);
1194 rc = bnx2fc_initiate_abts(io_req);
1195 } else {
1196 printk(KERN_ERR PFX "eh_abort: io_req (xid = 0x%x) " 1227 printk(KERN_ERR PFX "eh_abort: io_req (xid = 0x%x) "
1197 "already in abts processing\n", io_req->xid); 1228 "already in abts processing\n", io_req->xid);
1198 if (cancel_delayed_work(&io_req->timeout_work)) 1229 if (cancel_delayed_work(&io_req->timeout_work))
1199 kref_put(&io_req->refcount, 1230 kref_put(&io_req->refcount,
1200 bnx2fc_cmd_release); /* drop timer hold */ 1231 bnx2fc_cmd_release); /* drop timer hold */
1201 bnx2fc_initiate_cleanup(io_req); 1232 rc = bnx2fc_expl_logo(lport, io_req);
1233 goto out;
1234 }
1202 1235
1236 /* Cancel the current timer running on this io_req */
1237 if (cancel_delayed_work(&io_req->timeout_work))
1238 kref_put(&io_req->refcount,
1239 bnx2fc_cmd_release); /* drop timer hold */
1240 set_bit(BNX2FC_FLAG_EH_ABORT, &io_req->req_flags);
1241 io_req->wait_for_comp = 1;
1242 rc = bnx2fc_initiate_abts(io_req);
1243 if (rc == FAILED) {
1244 bnx2fc_initiate_cleanup(io_req);
1203 spin_unlock_bh(&tgt->tgt_lock); 1245 spin_unlock_bh(&tgt->tgt_lock);
1204
1205 wait_for_completion(&io_req->tm_done); 1246 wait_for_completion(&io_req->tm_done);
1206
1207 spin_lock_bh(&tgt->tgt_lock); 1247 spin_lock_bh(&tgt->tgt_lock);
1208 io_req->wait_for_comp = 0; 1248 io_req->wait_for_comp = 0;
1209 rdata = io_req->tgt->rdata; 1249 goto done;
1210 logo_issued = test_and_set_bit(BNX2FC_FLAG_EXPL_LOGO,
1211 &tgt->flags);
1212 kref_put(&io_req->refcount, bnx2fc_cmd_release);
1213 spin_unlock_bh(&tgt->tgt_lock);
1214
1215 if (!logo_issued) {
1216 BNX2FC_IO_DBG(io_req, "Expl logo - tgt flags = 0x%lx\n",
1217 tgt->flags);
1218 mutex_lock(&lport->disc.disc_mutex);
1219 lport->tt.rport_logoff(rdata);
1220 mutex_unlock(&lport->disc.disc_mutex);
1221 do {
1222 msleep(BNX2FC_RELOGIN_WAIT_TIME);
1223 /*
1224 * If session not recovered, let SCSI-ml
1225 * escalate error recovery.
1226 */
1227 if (wait_cnt++ > BNX2FC_RELOGIN_WAIT_CNT)
1228 return FAILED;
1229 } while (!test_bit(BNX2FC_FLAG_SESSION_READY,
1230 &tgt->flags));
1231 }
1232 return SUCCESS;
1233 }
1234 if (rc == FAILED) {
1235 kref_put(&io_req->refcount, bnx2fc_cmd_release);
1236 spin_unlock_bh(&tgt->tgt_lock);
1237 return rc;
1238 } 1250 }
1239 spin_unlock_bh(&tgt->tgt_lock); 1251 spin_unlock_bh(&tgt->tgt_lock);
1240 1252
@@ -1247,7 +1259,8 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
1247 /* Let the scsi-ml try to recover this command */ 1259 /* Let the scsi-ml try to recover this command */
1248 printk(KERN_ERR PFX "abort failed, xid = 0x%x\n", 1260 printk(KERN_ERR PFX "abort failed, xid = 0x%x\n",
1249 io_req->xid); 1261 io_req->xid);
1250 rc = FAILED; 1262 rc = bnx2fc_expl_logo(lport, io_req);
1263 goto out;
1251 } else { 1264 } else {
1252 /* 1265 /*
1253 * We come here even when there was a race condition 1266 * We come here even when there was a race condition
@@ -1259,9 +1272,10 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
1259 bnx2fc_scsi_done(io_req, DID_ABORT); 1272 bnx2fc_scsi_done(io_req, DID_ABORT);
1260 kref_put(&io_req->refcount, bnx2fc_cmd_release); 1273 kref_put(&io_req->refcount, bnx2fc_cmd_release);
1261 } 1274 }
1262 1275done:
1263 /* release the reference taken in eh_abort */ 1276 /* release the reference taken in eh_abort */
1264 kref_put(&io_req->refcount, bnx2fc_cmd_release); 1277 kref_put(&io_req->refcount, bnx2fc_cmd_release);
1278out:
1265 spin_unlock_bh(&tgt->tgt_lock); 1279 spin_unlock_bh(&tgt->tgt_lock);
1266 return rc; 1280 return rc;
1267} 1281}
diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
index c1800b531270..d3ee231a5680 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
@@ -213,8 +213,17 @@ void bnx2fc_flush_active_ios(struct bnx2fc_rport *tgt)
213 213
214 BNX2FC_IO_DBG(io_req, "retire_queue flush\n"); 214 BNX2FC_IO_DBG(io_req, "retire_queue flush\n");
215 215
216 if (cancel_delayed_work(&io_req->timeout_work)) 216 if (cancel_delayed_work(&io_req->timeout_work)) {
217 if (test_and_clear_bit(BNX2FC_FLAG_EH_ABORT,
218 &io_req->req_flags)) {
219 /* Handle eh_abort timeout */
220 BNX2FC_IO_DBG(io_req, "eh_abort for IO "
221 "in retire_q\n");
222 if (io_req->wait_for_comp)
223 complete(&io_req->tm_done);
224 }
217 kref_put(&io_req->refcount, bnx2fc_cmd_release); 225 kref_put(&io_req->refcount, bnx2fc_cmd_release);
226 }
218 227
219 clear_bit(BNX2FC_FLAG_ISSUE_RRQ, &io_req->req_flags); 228 clear_bit(BNX2FC_FLAG_ISSUE_RRQ, &io_req->req_flags);
220 } 229 }