summaryrefslogtreecommitdiff
path: root/drivers/scsi/lpfc/lpfc_els.c
diff options
context:
space:
mode:
authorJustin Tee <justin.tee@broadcom.com>2023-01-09 15:33:12 -0800
committerMartin K. Petersen <martin.petersen@oracle.com>2023-01-12 00:03:14 -0500
commitc051f1a424a15b73c493090a9f1c0273398b1637 (patch)
treec23bc55192a62bc8d03fcf6408c8954add3a809e /drivers/scsi/lpfc/lpfc_els.c
parentecdf4ddf4eb7a9135abdb358e98a8e6c1e8effe6 (diff)
scsi: lpfc: Exit PRLI completion handling early if ndlp not in PRLI_ISSUE state
In a large SAN testing configuration, frequent target port toggle tests are occasionally resulting in missing lun path rediscoveries. An outstanding PRLI can be inflight when a target RSCN dissappearance occurs, causing the driver to retry PRLIs using invalid rpi contexts. Fix by verifying that an ndlp's state was not restarted from PRLI_ISSUE due to an intermediate RSCN. If not in a valid state, early exit PRLI completion handling. The last follow up RSCN indicating target reappearance retriggers PLOGI/PRLI with a valid rpi context and is expected to succeed in LUN path rediscovery. Signed-off-by: Justin Tee <justin.tee@broadcom.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_els.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c28
1 files changed, 26 insertions, 2 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 919741bbe267..4d3b8f2036d2 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -2373,15 +2373,30 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
/* PRLI failed */
lpfc_printf_vlog(vport, mode, loglevel,
"2754 PRLI failure DID:%06X Status:x%x/x%x, "
- "data: x%x\n",
+ "data: x%x x%x\n",
ndlp->nlp_DID, ulp_status,
- ulp_word4, ndlp->fc4_prli_sent);
+ ulp_word4, ndlp->nlp_state,
+ ndlp->fc4_prli_sent);
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
if (!lpfc_error_lost_link(ulp_status, ulp_word4))
lpfc_disc_state_machine(vport, ndlp, cmdiocb,
NLP_EVT_CMPL_PRLI);
+ /* The following condition catches an inflight transition
+ * mismatch typically caused by an RSCN. Skip any
+ * processing to allow recovery.
+ */
+ if (ndlp->nlp_state >= NLP_STE_PLOGI_ISSUE &&
+ ndlp->nlp_state <= NLP_STE_REG_LOGIN_ISSUE) {
+ lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE,
+ "2784 PRLI cmpl: state mismatch "
+ "DID x%06x nstate x%x nflag x%x\n",
+ ndlp->nlp_DID, ndlp->nlp_state,
+ ndlp->nlp_flag);
+ goto out;
+ }
+
/*
* For P2P topology, retain the node so that PLOGI can be
* attempted on it again.
@@ -4673,6 +4688,15 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
/* the nameserver fails */
maxretry = 0;
delay = 100;
+ } else if (cmd == ELS_CMD_PRLI &&
+ ndlp->nlp_state != NLP_STE_PRLI_ISSUE) {
+ /* State-command disagreement. The PRLI was
+ * failed with an invalid rpi meaning there
+ * some unexpected state change. Don't retry.
+ */
+ maxretry = 0;
+ retry = 0;
+ break;
}
retry = 1;
break;