diff options
-rw-r--r-- | drivers/scsi/bnx2fc/bnx2fc_io.c | 106 | ||||
-rw-r--r-- | drivers/scsi/bnx2fc/bnx2fc_tgt.c | 11 |
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 | ||
1092 | int 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 | 1275 | done: | |
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); |
1278 | out: | ||
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 | } |