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