From: Mike Christie <[EMAIL PROTECTED]>
If fc_exch_recv is completing the ep while fc_fcp.c is calling
fc_seq_exch_abort then we could hit the WARN_ON for the completion
check. Instead of warning we just want to fail the fc_seq_exch_abort
call.
This also adds a check in fc_seq_exch_abort for if we are
sending an abort. There is no point in sending another one.
Signed-off-by: Mike Christie <[EMAIL PROTECTED]>
---
drivers/scsi/libfc/fc_exch.c | 75 +++++++++++++++++++++++++-----------------
1 files changed, 45 insertions(+), 30 deletions(-)
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 377d165..66b1c0d 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -138,6 +138,7 @@ static void fc_seq_ls_rjt(struct fc_seq *, enum
fc_els_rjt_reason,
enum fc_els_rjt_explan);
static void fc_exch_els_rec(struct fc_seq *, struct fc_frame *);
static void fc_exch_els_rrq(struct fc_seq *, struct fc_frame *);
+static struct fc_seq *fc_seq_start_next_locked(struct fc_seq *sp);
/*
* Internal implementation notes.
@@ -352,35 +353,43 @@ int fc_seq_exch_abort(const struct fc_seq *req_sp)
ep = fc_seq_exch(req_sp);
+ spin_lock_bh(&ep->ex_lock);
+ if (ep->esb_stat & (ESB_ST_COMPLETE | ESB_ST_ABNORMAL)) {
+ spin_unlock_bh(&ep->ex_lock);
+ return -ENXIO;
+ }
+
/*
* Send the abort on a new sequence if possible.
*/
- error = -ENOMEM;
- sp = fc_seq_start_next(&ep->seq);
- if (sp) {
- spin_lock_bh(&ep->ex_lock);
- sp->f_ctl |= FC_FC_SEQ_INIT;
- ep->esb_stat |= ESB_ST_SEQ_INIT | ESB_ST_ABNORMAL;
- fc_exch_timer_set_locked(ep, ep->r_a_tov);
+ sp = fc_seq_start_next_locked(&ep->seq);
+ if (!sp) {
spin_unlock_bh(&ep->ex_lock);
+ return -ENOMEM;
+ }
- /*
- * If not logged into the fabric, don't send ABTS but leave
- * sequence active until next timeout.
- */
- if (!ep->sid)
- return 0;
+ sp->f_ctl |= FC_FC_SEQ_INIT;
+ ep->esb_stat |= ESB_ST_SEQ_INIT | ESB_ST_ABNORMAL;
+ fc_exch_timer_set_locked(ep, ep->r_a_tov);
+ spin_unlock_bh(&ep->ex_lock);
+
+ /*
+ * If not logged into the fabric, don't send ABTS but leave
+ * sequence active until next timeout.
+ */
+ if (!ep->sid)
+ return 0;
+
+ /*
+ * Send an abort for the sequence that timed out.
+ */
+ fp = fc_frame_alloc(ep->lp, 0);
+ if (fp) {
+ fc_frame_setup(fp, FC_RCTL_BA_ABTS, FC_TYPE_BLS);
+ error = fc_seq_send(ep->lp, sp, fp, FC_FC_END_SEQ);
+ } else
+ error = -ENOBUFS;
- /*
- * Send an abort for the sequence that timed out.
- */
- fp = fc_frame_alloc(ep->lp, 0);
- if (fp) {
- fc_frame_setup(fp, FC_RCTL_BA_ABTS, FC_TYPE_BLS);
- error = fc_seq_send(ep->lp, sp, fp, FC_FC_END_SEQ);
- } else
- error = -ENOBUFS;
- }
return error;
}
EXPORT_SYMBOL(fc_seq_exch_abort);
@@ -717,11 +726,11 @@ fc_seq_lookup_recip(struct fc_exch_mgr *mp, struct
fc_frame *fp)
*/
if (fc_sof_is_init(fr_sof(fp))) {
sp = fc_seq_start_next(&ep->seq);
- sp->id = fh->fh_seq_id;
if (!sp) {
reject = FC_RJT_SEQ_XS; /* exchange shortage */
goto out;
}
+ sp->id = fh->fh_seq_id;
sp->ssb_stat |= SSB_ST_RESP;
} else {
sp = &ep->seq;
@@ -793,6 +802,16 @@ static void fc_exch_set_addr(struct fc_exch *ep,
}
}
+static struct fc_seq *fc_seq_start_next_locked(struct fc_seq *sp)
+{
+ struct fc_exch *ep = fc_seq_exch(sp);
+
+ sp = fc_seq_alloc(ep, ep->seq_id++);
+ if (fc_exch_debug)
+ FC_DBG("exch %4x f_ctl %6x seq %2x f_ctl %6x\n",
+ ep->xid, ep->f_ctl, sp->id, sp->f_ctl);
+ return sp;
+}
/*
* Allocate a new sequence on the same exchange as the supplied sequence.
* This will never return NULL.
@@ -803,13 +822,9 @@ struct fc_seq *fc_seq_start_next(struct fc_seq *sp)
spin_lock_bh(&ep->ex_lock);
WARN_ON((ep->esb_stat & ESB_ST_COMPLETE) != 0);
-
- sp = fc_seq_alloc(ep, ep->seq_id++);
-
- if (fc_exch_debug)
- FC_DBG("exch %4x f_ctl %6x seq %2x f_ctl %6x\n",
- ep->xid, ep->f_ctl, sp->id, sp->f_ctl);
+ sp = fc_seq_start_next_locked(sp);
spin_unlock_bh(&ep->ex_lock);
+
return sp;
}
EXPORT_SYMBOL(fc_seq_start_next);
--
1.5.4.1
_______________________________________________
devel mailing list
[email protected]
http://www.open-fcoe.org/mailman/listinfo/devel