|
@@ -1089,6 +1089,48 @@ int bnx2fc_eh_device_reset(struct scsi_cmnd *sc_cmd)
|
|
|
return bnx2fc_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET);
|
|
|
}
|
|
|
|
|
|
+int bnx2fc_expl_logo(struct fc_lport *lport, struct bnx2fc_cmd *io_req)
|
|
|
+{
|
|
|
+ struct bnx2fc_rport *tgt = io_req->tgt;
|
|
|
+ struct fc_rport_priv *rdata = tgt->rdata;
|
|
|
+ int logo_issued;
|
|
|
+ int rc = SUCCESS;
|
|
|
+ int wait_cnt = 0;
|
|
|
+
|
|
|
+ BNX2FC_IO_DBG(io_req, "Expl logo - tgt flags = 0x%lx\n",
|
|
|
+ tgt->flags);
|
|
|
+ logo_issued = test_and_set_bit(BNX2FC_FLAG_EXPL_LOGO,
|
|
|
+ &tgt->flags);
|
|
|
+ io_req->wait_for_comp = 1;
|
|
|
+ bnx2fc_initiate_cleanup(io_req);
|
|
|
+
|
|
|
+ spin_unlock_bh(&tgt->tgt_lock);
|
|
|
+
|
|
|
+ wait_for_completion(&io_req->tm_done);
|
|
|
+
|
|
|
+ io_req->wait_for_comp = 0;
|
|
|
+ /*
|
|
|
+ * release the reference taken in eh_abort to allow the
|
|
|
+ * target to re-login after flushing IOs
|
|
|
+ */
|
|
|
+ kref_put(&io_req->refcount, bnx2fc_cmd_release);
|
|
|
+
|
|
|
+ if (!logo_issued) {
|
|
|
+ clear_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags);
|
|
|
+ mutex_lock(&lport->disc.disc_mutex);
|
|
|
+ lport->tt.rport_logoff(rdata);
|
|
|
+ mutex_unlock(&lport->disc.disc_mutex);
|
|
|
+ do {
|
|
|
+ msleep(BNX2FC_RELOGIN_WAIT_TIME);
|
|
|
+ if (wait_cnt++ > BNX2FC_RELOGIN_WAIT_CNT) {
|
|
|
+ rc = FAILED;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } while (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags));
|
|
|
+ }
|
|
|
+ spin_lock_bh(&tgt->tgt_lock);
|
|
|
+ return rc;
|
|
|
+}
|
|
|
/**
|
|
|
* bnx2fc_eh_abort - eh_abort_handler api to abort an outstanding
|
|
|
* SCSI command
|
|
@@ -1103,10 +1145,7 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
|
|
|
struct fc_rport_libfc_priv *rp = rport->dd_data;
|
|
|
struct bnx2fc_cmd *io_req;
|
|
|
struct fc_lport *lport;
|
|
|
- struct fc_rport_priv *rdata;
|
|
|
struct bnx2fc_rport *tgt;
|
|
|
- int logo_issued;
|
|
|
- int wait_cnt = 0;
|
|
|
int rc = FAILED;
|
|
|
|
|
|
|
|
@@ -1183,58 +1222,31 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
|
|
|
list_add_tail(&io_req->link, &tgt->io_retire_queue);
|
|
|
|
|
|
init_completion(&io_req->tm_done);
|
|
|
- io_req->wait_for_comp = 1;
|
|
|
|
|
|
- if (!test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS, &io_req->req_flags)) {
|
|
|
- /* Cancel the current timer running on this io_req */
|
|
|
- if (cancel_delayed_work(&io_req->timeout_work))
|
|
|
- kref_put(&io_req->refcount,
|
|
|
- bnx2fc_cmd_release); /* drop timer hold */
|
|
|
- set_bit(BNX2FC_FLAG_EH_ABORT, &io_req->req_flags);
|
|
|
- rc = bnx2fc_initiate_abts(io_req);
|
|
|
- } else {
|
|
|
+ if (test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS, &io_req->req_flags)) {
|
|
|
printk(KERN_ERR PFX "eh_abort: io_req (xid = 0x%x) "
|
|
|
"already in abts processing\n", io_req->xid);
|
|
|
if (cancel_delayed_work(&io_req->timeout_work))
|
|
|
kref_put(&io_req->refcount,
|
|
|
bnx2fc_cmd_release); /* drop timer hold */
|
|
|
- bnx2fc_initiate_cleanup(io_req);
|
|
|
+ rc = bnx2fc_expl_logo(lport, io_req);
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
|
|
|
+ /* Cancel the current timer running on this io_req */
|
|
|
+ if (cancel_delayed_work(&io_req->timeout_work))
|
|
|
+ kref_put(&io_req->refcount,
|
|
|
+ bnx2fc_cmd_release); /* drop timer hold */
|
|
|
+ set_bit(BNX2FC_FLAG_EH_ABORT, &io_req->req_flags);
|
|
|
+ io_req->wait_for_comp = 1;
|
|
|
+ rc = bnx2fc_initiate_abts(io_req);
|
|
|
+ if (rc == FAILED) {
|
|
|
+ bnx2fc_initiate_cleanup(io_req);
|
|
|
spin_unlock_bh(&tgt->tgt_lock);
|
|
|
-
|
|
|
wait_for_completion(&io_req->tm_done);
|
|
|
-
|
|
|
spin_lock_bh(&tgt->tgt_lock);
|
|
|
io_req->wait_for_comp = 0;
|
|
|
- rdata = io_req->tgt->rdata;
|
|
|
- logo_issued = test_and_set_bit(BNX2FC_FLAG_EXPL_LOGO,
|
|
|
- &tgt->flags);
|
|
|
- kref_put(&io_req->refcount, bnx2fc_cmd_release);
|
|
|
- spin_unlock_bh(&tgt->tgt_lock);
|
|
|
-
|
|
|
- if (!logo_issued) {
|
|
|
- BNX2FC_IO_DBG(io_req, "Expl logo - tgt flags = 0x%lx\n",
|
|
|
- tgt->flags);
|
|
|
- mutex_lock(&lport->disc.disc_mutex);
|
|
|
- lport->tt.rport_logoff(rdata);
|
|
|
- mutex_unlock(&lport->disc.disc_mutex);
|
|
|
- do {
|
|
|
- msleep(BNX2FC_RELOGIN_WAIT_TIME);
|
|
|
- /*
|
|
|
- * If session not recovered, let SCSI-ml
|
|
|
- * escalate error recovery.
|
|
|
- */
|
|
|
- if (wait_cnt++ > BNX2FC_RELOGIN_WAIT_CNT)
|
|
|
- return FAILED;
|
|
|
- } while (!test_bit(BNX2FC_FLAG_SESSION_READY,
|
|
|
- &tgt->flags));
|
|
|
- }
|
|
|
- return SUCCESS;
|
|
|
- }
|
|
|
- if (rc == FAILED) {
|
|
|
- kref_put(&io_req->refcount, bnx2fc_cmd_release);
|
|
|
- spin_unlock_bh(&tgt->tgt_lock);
|
|
|
- return rc;
|
|
|
+ goto done;
|
|
|
}
|
|
|
spin_unlock_bh(&tgt->tgt_lock);
|
|
|
|
|
@@ -1247,7 +1259,8 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
|
|
|
/* Let the scsi-ml try to recover this command */
|
|
|
printk(KERN_ERR PFX "abort failed, xid = 0x%x\n",
|
|
|
io_req->xid);
|
|
|
- rc = FAILED;
|
|
|
+ rc = bnx2fc_expl_logo(lport, io_req);
|
|
|
+ goto out;
|
|
|
} else {
|
|
|
/*
|
|
|
* We come here even when there was a race condition
|
|
@@ -1259,9 +1272,10 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
|
|
|
bnx2fc_scsi_done(io_req, DID_ABORT);
|
|
|
kref_put(&io_req->refcount, bnx2fc_cmd_release);
|
|
|
}
|
|
|
-
|
|
|
+done:
|
|
|
/* release the reference taken in eh_abort */
|
|
|
kref_put(&io_req->refcount, bnx2fc_cmd_release);
|
|
|
+out:
|
|
|
spin_unlock_bh(&tgt->tgt_lock);
|
|
|
return rc;
|
|
|
}
|