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

Reply via email to