From: Mike Christie <[EMAIL PROTECTED]>

For most functions where we do a hold, lock, release
the caller has hold on the ep already, so there is no
point in doing this.

The exception was fc_exch_reset. I changed this so we hold the
em_lock when looping over the ex_list and take a hold like is
done in the the find function.

It also looked like fc_exch_reset could run while fc_exch_recv was
running. If fc_exch_recv had passed the port state checks then it
could release eps next to the one fc_exch_reset was working on
and list_for_each_entry cannot handle that. I just restart the loop
for this case, so we do not return from the function until we
have completed one loop over the list.

Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
 drivers/scsi/libfc/fc_exch.c |   24 +++++++++++++++++-------
 1 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 6b4236e..377d165 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -408,13 +408,11 @@ static void fc_exch_timeout(unsigned long ep_arg)
                ep->esb_stat |= ESB_ST_COMPLETE;
                spin_unlock_bh(&ep->ex_lock);
        } else {
-               fc_exch_hold(ep);
                resp = ep->resp;
                ep->resp = NULL;
                arg = ep->resp_arg;
                spin_unlock_bh(&ep->ex_lock);
                fc_seq_exch_abort(sp);
-               fc_exch_release(ep);
 
                if (resp)
                        resp(sp, ERR_PTR(-FC_EX_TIMEOUT), arg);
@@ -1262,7 +1260,6 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct 
fc_frame *fp)
        if (fc_exch_debug)
                FC_DBG("exch: BLS rctl %x - %s\n",
                       fh->fh_r_ctl, fc_exch_rctl_name(fh->fh_r_ctl));
-       fc_exch_hold(ep);
        spin_lock_bh(&ep->ex_lock);
        switch (fh->fh_r_ctl) {
        case FC_RCTL_BA_ACC:
@@ -1293,7 +1290,6 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct 
fc_frame *fp)
        if (ntoh24(fh->fh_f_ctl) & FC_FC_LAST_SEQ)
                fc_exch_complete_locked(ep);
        spin_unlock_bh(&ep->ex_lock);
-       fc_exch_release(ep);
        fc_frame_free(fp);
 }
 
@@ -1408,7 +1404,6 @@ static void fc_exch_reset(struct fc_exch *ep)
        void (*resp)(struct fc_seq *, struct fc_frame *, void *);
        void *arg;
 
-       fc_exch_hold(ep);
        spin_lock_bh(&ep->ex_lock);
        resp = ep->resp;
        ep->resp = NULL;
@@ -1426,7 +1421,6 @@ static void fc_exch_reset(struct fc_exch *ep)
        spin_unlock_bh(&ep->ex_lock);
        if (resp)
                resp(sp, ERR_PTR(-FC_EX_CLOSED), arg);
-       fc_exch_release(ep);
 }
 
 /*
@@ -1439,11 +1433,27 @@ void fc_exch_mgr_reset(struct fc_exch_mgr *mp, u32 sid, 
u32 did)
        struct fc_exch *ep;
        struct fc_exch *next;
 
+       spin_lock_bh(&mp->em_lock);
+restart:
        list_for_each_entry_safe(ep, next, &mp->ex_list, ex_list) {
                if ((sid == 0 || sid == ep->sid) &&
-                   (did == 0 || did == ep->did))
+                   (did == 0 || did == ep->did)) {
+                       fc_exch_hold(ep);
+                       spin_unlock_bh(&mp->em_lock);
+
                        fc_exch_reset(ep);
+
+                       fc_exch_release(ep);
+                       spin_lock_bh(&mp->em_lock);
+
+                       /*
+                        * must restart loop incase while lock was down
+                        * multiple eps were released.
+                        */
+                       goto restart;
+               }
        }
+       spin_unlock_bh(&mp->em_lock);
 }
 EXPORT_SYMBOL(fc_exch_mgr_reset);
 
-- 
1.5.4.1

_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel

Reply via email to