From d66595d78643e42e5c75c65b540aa114708b2850 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 13 Aug 2008 02:29:38 -0500 Subject: [PATCH 07/23] libfc: fix RRQ handling I think if we send a RRQ then when fc_exch_rrq_resp completes successfully we must drop the hold taken in fc_exch_abts_resp. The error handling in this patch is crap. There is none if we get a reject. I cannot test this patch. I have not been able to hit the code path. Does the software targets support this? If so I can hack something up to test it. But for now this should do, and is better than leaking the ep on successful completion. Patch is completly untested. Signed-off-by: Mike Christie --- drivers/scsi/libfc/fc_exch.c | 25 ++++++++++++++++++++----- 1 files changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 66b1c0d..71682bd 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1294,7 +1294,7 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp) ap->ba_seq_id == ep->seq_id) && low != high) { ep->esb_stat |= ESB_ST_REC_QUAL; fc_exch_hold(ep); /* hold for recovery qualifier */ - fc_exch_timer_set_locked(ep, 2 * ep->r_a_tov); + fc_exch_timer_set_locked(ep, ep->r_a_tov); } break; case FC_RCTL_BA_RJT: @@ -1575,18 +1575,33 @@ reject: * Handle response from RRQ. * Not much to do here, really. * Should report errors. + * + * TODO: fix error handler. */ static void fc_exch_rrq_resp(struct fc_seq *sp, struct fc_frame *fp, void *arg) { + struct fc_exch *aborted_ep = arg; unsigned int op; - if (IS_ERR(fp)) + if (IS_ERR(fp)) { + int err = PTR_ERR(fp); + + FC_DBG("Cannot process RRQ, because of frame error %d\n", err); return; + } + op = fc_frame_payload_op(fp); - if (op == ELS_LS_RJT) + switch (op) { + case ELS_LS_RJT: FC_DBG("LS_RJT for RRQ"); - else if (op != ELS_LS_ACC) + break; + case ELS_LS_ACC: + fc_exch_release(aborted_ep); /* drop hold for rec qual */ + break; + default: FC_DBG("unexpected response op %x for RRQ", op); + } + fc_frame_free(fp); } @@ -1618,7 +1633,7 @@ static void fc_exch_rrq(struct fc_exch *ep) did = ep->did; if (ep->esb_stat & ESB_ST_RESP) did = ep->sid; - if (!fc_exch_seq_send(lp, fp, fc_exch_rrq_resp, NULL, lp->e_d_tov, + if (!fc_exch_seq_send(lp, fp, fc_exch_rrq_resp, ep, lp->e_d_tov, lp->fid, did, FC_FC_SEQ_INIT | FC_FC_END_SEQ)) fc_exch_timer_set(ep, ep->r_a_tov); } -- 1.5.5.1