If no response to abort request then fc_exch_timeout() will
occur in ESB_ST_ABNORMAL, in this state
1. we need to free exchanges for non fcp upper layers
2. Do not call exch resp for FCP types since fc_fcp.c will do its
own cleanup in this case. Anyway exch timer is not requested by
FCP in this case, therefore no FC_EX_TIMEOUT events to FCP types
exchanges also.
Signed-off-by: Vasu Dev <[EMAIL PROTECTED]>
---
drivers/scsi/libfc/fc_exch.c | 90 ++++++++++++++++++++++--------------------
1 files changed, 47 insertions(+), 43 deletions(-)
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index b7f44c2..4ed6bdd 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -305,6 +305,44 @@ static void fc_exch_release(struct fc_exch *ep)
}
}
+static int fc_exch_done_locked(struct fc_exch *ep)
+{
+ int rc = 1;
+
+ /*
+ * We must check for completion in case there are two threads
+ * tyring to complete this. But the rrq code will reuse the
+ * ep, and in that case we only clear the resp and set it as
+ * complete, so it can be reused by the timer to send the rrq.
+ */
+ ep->resp = NULL;
+ if (ep->state & FC_EX_DONE)
+ return rc;
+ ep->esb_stat |= ESB_ST_COMPLETE;
+
+ if (!(ep->esb_stat & ESB_ST_REC_QUAL)) {
+ ep->state |= FC_EX_DONE;
+ if (del_timer(&ep->ex_timer))
+ atomic_dec(&ep->ex_refcnt); /* drop hold for timer */
+ atomic_dec(&ep->ex_refcnt); /* drop hold from alloc */
+ rc = 0;
+ }
+ return rc;
+}
+
+static void fc_exch_mgr_delete_ep(struct fc_exch *ep)
+{
+ struct fc_exch_mgr *mp;
+
+ mp = ep->em;
+ spin_lock_bh(&mp->em_lock);
+ WARN_ON(mp->total_exches <= 0);
+ mp->total_exches--;
+ mp->exches[ep->xid - mp->min_xid] = NULL;
+ list_del(&ep->ex_list);
+ spin_unlock_bh(&mp->em_lock);
+}
+
/*
* Internal version of fc_exch_timer_set - used with lock held.
*/
@@ -398,6 +436,7 @@ static void fc_exch_timeout(unsigned long ep_arg)
void (*resp)(struct fc_seq *, struct fc_frame *fp, void *arg);
void *arg;
u32 e_stat;
+ int rc = 1;
spin_lock_bh(&ep->ex_lock);
if (ep->state & (FC_EX_RST_CLEANUP | FC_EX_DONE))
@@ -410,16 +449,19 @@ static void fc_exch_timeout(unsigned long ep_arg)
if (e_stat & ESB_ST_REC_QUAL)
fc_exch_rrq(ep);
goto done;
- } else if (!(e_stat & ESB_ST_ABNORMAL)) {
- resp = ep->resp;
- arg = ep->resp_arg;
+ } else if (ep->fh_type != FC_TYPE_FCP) {
/*
* For FCP commands fc_fcp.c will manage the completion.
* For all others fc_exch.c will handle.
*/
- if (ep->fh_type != FC_TYPE_FCP)
- ep->resp = NULL;
+ resp = ep->resp;
+ arg = ep->resp_arg;
+ ep->resp = NULL;
+ if (e_stat & ESB_ST_ABNORMAL)
+ rc = fc_exch_done_locked(ep);
spin_unlock_bh(&ep->ex_lock);
+ if (!rc)
+ fc_exch_mgr_delete_ep(ep);
if (resp)
resp(sp, ERR_PTR(-FC_EX_TIMEOUT), arg);
fc_seq_exch_abort(sp);
@@ -560,44 +602,6 @@ static struct fc_exch *fc_exch_find(struct fc_exch_mgr
*mp, u16 xid)
return ep;
}
-static void fc_exch_mgr_delete_ep(struct fc_exch *ep)
-{
- struct fc_exch_mgr *mp;
-
- mp = ep->em;
- spin_lock_bh(&mp->em_lock);
- WARN_ON(mp->total_exches <= 0);
- mp->total_exches--;
- mp->exches[ep->xid - mp->min_xid] = NULL;
- list_del(&ep->ex_list);
- spin_unlock_bh(&mp->em_lock);
-}
-
-static int fc_exch_done_locked(struct fc_exch *ep)
-{
- int rc = 1;
-
- /*
- * We must check for completion in case there are two threads
- * tyring to complete this. But the rrq code will reuse the
- * ep, and in that case we only clear the resp and set it as
- * complete, so it can be reused by the timer to send the rrq.
- */
- ep->resp = NULL;
- if (ep->state & FC_EX_DONE)
- return rc;
- ep->esb_stat |= ESB_ST_COMPLETE;
-
- if (!(ep->esb_stat & ESB_ST_REC_QUAL)) {
- ep->state |= FC_EX_DONE;
- if (del_timer(&ep->ex_timer))
- atomic_dec(&ep->ex_refcnt); /* drop hold for timer */
- atomic_dec(&ep->ex_refcnt); /* drop hold from alloc */
- rc = 0;
- }
- return rc;
-}
-
void fc_exch_done(struct fc_seq *sp)
{
struct fc_exch *ep = fc_seq_exch(sp);
_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel