Skip to content

Commit

Permalink
scsi: qedf: Avoid invoking response handler twice if ep is already co…
Browse files Browse the repository at this point in the history
…mpleted.

  Issue :- race condition getting hit between the response handler
  get called because of the exchange_mgr_reset() which clear out all
  the active XID and the response we get via interrupt as the same time

  Below are the sequence of events occurring in case of
  "issue/race condition" :-
  rport ba0200: Port timeout, state PLOGI
  rport ba0200: Port entered PLOGI state from PLOGI state
  xid 1052: Exchange timer armed : 20000 msecs      xid timer armed here
  rport ba0200: Received LOGO request while in state PLOGI
  rport ba0200: Delete port
  rport ba0200: work event 3
  rport ba0200: lld callback ev 3
  bnx2fc: rport_event_hdlr: event = 3, port_id = 0xba0200
  bnx2fc: ba0200 - rport not created Yet!!
  /* Here we reset any outstanding exchanges before
   freeing rport using the exch_mgr_reset() */
  xid 1052: Exchange timer canceled
  /*Here we got two response for one xid*/
  xid 1052: invoking resp(), esb 20000000 state 3
  xid 1052: invoking resp(), esb 20000000 state 3
  xid 1052: fc_rport_plogi_resp() : ep->resp_active 2
  xid 1052: fc_rport_plogi_resp() : ep->resp_active 2

Signed-off-by: Javed Hasan <jhasan@marvell.com>
  • Loading branch information
javed-h authored and intel-lab-lkp committed Dec 15, 2020
1 parent cb52531 commit eafc014
Showing 1 changed file with 14 additions and 2 deletions.
16 changes: 14 additions & 2 deletions drivers/scsi/libfc/fc_exch.c
Expand Up @@ -1623,8 +1623,13 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
rc = fc_exch_done_locked(ep);
WARN_ON(fc_seq_exch(sp) != ep);
spin_unlock_bh(&ep->ex_lock);
if (!rc)
if (!rc) {
fc_exch_delete(ep);
} else {
FC_EXCH_DBG(ep, " ep is completed already,
hence skip calling the resp\n");
goto skip_resp;
}
}

/*
Expand All @@ -1643,6 +1648,7 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
if (!fc_invoke_resp(ep, sp, fp))
fc_frame_free(fp);

skip_resp:
fc_exch_release(ep);
return;
rel:
Expand Down Expand Up @@ -1899,10 +1905,16 @@ static void fc_exch_reset(struct fc_exch *ep)

fc_exch_hold(ep);

if (!rc)
if (!rc) {
fc_exch_delete(ep);
} else {
FC_EXCH_DBG(ep, " ep is completed already,
hence skip calling the resp\n");
goto skip_resp;
}

fc_invoke_resp(ep, sp, ERR_PTR(-FC_EX_CLOSED));
skip_resp:
fc_seq_set_resp(sp, NULL, ep->arg);
fc_exch_release(ep);
}
Expand Down

0 comments on commit eafc014

Please sign in to comment.