aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/bnx2fc/bnx2fc_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/bnx2fc/bnx2fc_io.c')
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_io.c122
1 files changed, 75 insertions, 47 deletions
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c
index e897ce975bb8..4f7453b9e41e 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_io.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_io.c
@@ -810,8 +810,22 @@ retry_tmf:
810 spin_lock_bh(&tgt->tgt_lock); 810 spin_lock_bh(&tgt->tgt_lock);
811 811
812 io_req->wait_for_comp = 0; 812 io_req->wait_for_comp = 0;
813 if (!(test_bit(BNX2FC_FLAG_TM_COMPL, &io_req->req_flags))) 813 if (!(test_bit(BNX2FC_FLAG_TM_COMPL, &io_req->req_flags))) {
814 set_bit(BNX2FC_FLAG_TM_TIMEOUT, &io_req->req_flags); 814 set_bit(BNX2FC_FLAG_TM_TIMEOUT, &io_req->req_flags);
815 if (io_req->on_tmf_queue) {
816 list_del_init(&io_req->link);
817 io_req->on_tmf_queue = 0;
818 }
819 io_req->wait_for_comp = 1;
820 bnx2fc_initiate_cleanup(io_req);
821 spin_unlock_bh(&tgt->tgt_lock);
822 rc = wait_for_completion_timeout(&io_req->tm_done,
823 BNX2FC_FW_TIMEOUT);
824 spin_lock_bh(&tgt->tgt_lock);
825 io_req->wait_for_comp = 0;
826 if (!rc)
827 kref_put(&io_req->refcount, bnx2fc_cmd_release);
828 }
815 829
816 spin_unlock_bh(&tgt->tgt_lock); 830 spin_unlock_bh(&tgt->tgt_lock);
817 831
@@ -1089,6 +1103,48 @@ int bnx2fc_eh_device_reset(struct scsi_cmnd *sc_cmd)
1089 return bnx2fc_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET); 1103 return bnx2fc_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET);
1090} 1104}
1091 1105
1106int bnx2fc_expl_logo(struct fc_lport *lport, struct bnx2fc_cmd *io_req)
1107{
1108 struct bnx2fc_rport *tgt = io_req->tgt;
1109 struct fc_rport_priv *rdata = tgt->rdata;
1110 int logo_issued;
1111 int rc = SUCCESS;
1112 int wait_cnt = 0;
1113
1114 BNX2FC_IO_DBG(io_req, "Expl logo - tgt flags = 0x%lx\n",
1115 tgt->flags);
1116 logo_issued = test_and_set_bit(BNX2FC_FLAG_EXPL_LOGO,
1117 &tgt->flags);
1118 io_req->wait_for_comp = 1;
1119 bnx2fc_initiate_cleanup(io_req);
1120
1121 spin_unlock_bh(&tgt->tgt_lock);
1122
1123 wait_for_completion(&io_req->tm_done);
1124
1125 io_req->wait_for_comp = 0;
1126 /*
1127 * release the reference taken in eh_abort to allow the
1128 * target to re-login after flushing IOs
1129 */
1130 kref_put(&io_req->refcount, bnx2fc_cmd_release);
1131
1132 if (!logo_issued) {
1133 clear_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags);
1134 mutex_lock(&lport->disc.disc_mutex);
1135 lport->tt.rport_logoff(rdata);
1136 mutex_unlock(&lport->disc.disc_mutex);
1137 do {
1138 msleep(BNX2FC_RELOGIN_WAIT_TIME);
1139 if (wait_cnt++ > BNX2FC_RELOGIN_WAIT_CNT) {
1140 rc = FAILED;
1141 break;
1142 }
1143 } while (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags));
1144 }
1145 spin_lock_bh(&tgt->tgt_lock);
1146 return rc;
1147}
1092/** 1148/**
1093 * bnx2fc_eh_abort - eh_abort_handler api to abort an outstanding 1149 * bnx2fc_eh_abort - eh_abort_handler api to abort an outstanding
1094 * SCSI command 1150 * SCSI command
@@ -1103,10 +1159,7 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
1103 struct fc_rport_libfc_priv *rp = rport->dd_data; 1159 struct fc_rport_libfc_priv *rp = rport->dd_data;
1104 struct bnx2fc_cmd *io_req; 1160 struct bnx2fc_cmd *io_req;
1105 struct fc_lport *lport; 1161 struct fc_lport *lport;
1106 struct fc_rport_priv *rdata;
1107 struct bnx2fc_rport *tgt; 1162 struct bnx2fc_rport *tgt;
1108 int logo_issued;
1109 int wait_cnt = 0;
1110 int rc = FAILED; 1163 int rc = FAILED;
1111 1164
1112 1165
@@ -1183,58 +1236,31 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
1183 list_add_tail(&io_req->link, &tgt->io_retire_queue); 1236 list_add_tail(&io_req->link, &tgt->io_retire_queue);
1184 1237
1185 init_completion(&io_req->tm_done); 1238 init_completion(&io_req->tm_done);
1186 io_req->wait_for_comp = 1;
1187 1239
1188 if (!test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS, &io_req->req_flags)) { 1240 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) " 1241 printk(KERN_ERR PFX "eh_abort: io_req (xid = 0x%x) "
1197 "already in abts processing\n", io_req->xid); 1242 "already in abts processing\n", io_req->xid);
1198 if (cancel_delayed_work(&io_req->timeout_work)) 1243 if (cancel_delayed_work(&io_req->timeout_work))
1199 kref_put(&io_req->refcount, 1244 kref_put(&io_req->refcount,
1200 bnx2fc_cmd_release); /* drop timer hold */ 1245 bnx2fc_cmd_release); /* drop timer hold */
1201 bnx2fc_initiate_cleanup(io_req); 1246 rc = bnx2fc_expl_logo(lport, io_req);
1247 goto out;
1248 }
1202 1249
1250 /* Cancel the current timer running on this io_req */
1251 if (cancel_delayed_work(&io_req->timeout_work))
1252 kref_put(&io_req->refcount,
1253 bnx2fc_cmd_release); /* drop timer hold */
1254 set_bit(BNX2FC_FLAG_EH_ABORT, &io_req->req_flags);
1255 io_req->wait_for_comp = 1;
1256 rc = bnx2fc_initiate_abts(io_req);
1257 if (rc == FAILED) {
1258 bnx2fc_initiate_cleanup(io_req);
1203 spin_unlock_bh(&tgt->tgt_lock); 1259 spin_unlock_bh(&tgt->tgt_lock);
1204
1205 wait_for_completion(&io_req->tm_done); 1260 wait_for_completion(&io_req->tm_done);
1206
1207 spin_lock_bh(&tgt->tgt_lock); 1261 spin_lock_bh(&tgt->tgt_lock);
1208 io_req->wait_for_comp = 0; 1262 io_req->wait_for_comp = 0;
1209 rdata = io_req->tgt->rdata; 1263 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 } 1264 }
1239 spin_unlock_bh(&tgt->tgt_lock); 1265 spin_unlock_bh(&tgt->tgt_lock);
1240 1266
@@ -1247,7 +1273,8 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
1247 /* Let the scsi-ml try to recover this command */ 1273 /* Let the scsi-ml try to recover this command */
1248 printk(KERN_ERR PFX "abort failed, xid = 0x%x\n", 1274 printk(KERN_ERR PFX "abort failed, xid = 0x%x\n",
1249 io_req->xid); 1275 io_req->xid);
1250 rc = FAILED; 1276 rc = bnx2fc_expl_logo(lport, io_req);
1277 goto out;
1251 } else { 1278 } else {
1252 /* 1279 /*
1253 * We come here even when there was a race condition 1280 * We come here even when there was a race condition
@@ -1259,9 +1286,10 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
1259 bnx2fc_scsi_done(io_req, DID_ABORT); 1286 bnx2fc_scsi_done(io_req, DID_ABORT);
1260 kref_put(&io_req->refcount, bnx2fc_cmd_release); 1287 kref_put(&io_req->refcount, bnx2fc_cmd_release);
1261 } 1288 }
1262 1289done:
1263 /* release the reference taken in eh_abort */ 1290 /* release the reference taken in eh_abort */
1264 kref_put(&io_req->refcount, bnx2fc_cmd_release); 1291 kref_put(&io_req->refcount, bnx2fc_cmd_release);
1292out:
1265 spin_unlock_bh(&tgt->tgt_lock); 1293 spin_unlock_bh(&tgt->tgt_lock);
1266 return rc; 1294 return rc;
1267} 1295}