Daniel Wagner 546e11
From: James Smart <jsmart2021@gmail.com>
Daniel Wagner 546e11
Date: Fri, 14 May 2021 12:55:55 -0700
Daniel Wagner 546e11
Subject: scsi: lpfc: Ignore GID-FT response that may be received after a link
Daniel Wagner 546e11
 flip
Daniel Wagner 546e11
Patch-mainline: Queued in subsystem maintainer repository
Daniel Wagner 546e11
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git
Daniel Wagner 546e11
Git-commit: 04c1d9c50ae32d6efd0b71024b3829051821c7a2
Daniel Wagner 546e11
References: bsc#1186451
Daniel Wagner 546e11
Daniel Wagner 546e11
When a link bounce happens, there is a possibility that responses to
Daniel Wagner 546e11
requests posted prior to the link bounce could be received. This is
Daniel Wagner 546e11
problematic as the counter to track reglogin completion after link up can
Daniel Wagner 546e11
become out of sync with the real state.
Daniel Wagner 546e11
Daniel Wagner 546e11
As there is no reason to process a request made in a prior link up context,
Daniel Wagner 546e11
eliminate all the disturbance by tagging the request with the event_tag
Daniel Wagner 546e11
maintained by the SLI Port for the link. The event_tag will change on every
Daniel Wagner 546e11
link state transition.  As long as the tag matches the current event_tag,
Daniel Wagner 546e11
the response can be processed. If it doesn't match, just discard the
Daniel Wagner 546e11
response.
Daniel Wagner 546e11
Daniel Wagner 546e11
Link: https://lore.kernel.org/r/20210514195559.119853-8-jsmart2021@gmail.com
Daniel Wagner 546e11
Co-developed-by: Justin Tee <justin.tee@broadcom.com>
Daniel Wagner 546e11
Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Daniel Wagner 546e11
Signed-off-by: James Smart <jsmart2021@gmail.com>
Daniel Wagner 546e11
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Daniel Wagner 546e11
Acked-by: Daniel Wagner <dwagner@suse.de>
Daniel Wagner 546e11
---
Daniel Wagner 546e11
 drivers/scsi/lpfc/lpfc_ct.c  |   43 ++++++++++++++++++++++++++++++++++++-------
Daniel Wagner 546e11
 drivers/scsi/lpfc/lpfc_sli.h |    3 ++-
Daniel Wagner 546e11
 2 files changed, 38 insertions(+), 8 deletions(-)
Daniel Wagner 546e11
Daniel Wagner 546e11
--- a/drivers/scsi/lpfc/lpfc_ct.c
Daniel Wagner 546e11
+++ b/drivers/scsi/lpfc/lpfc_ct.c
Daniel Wagner 546e11
@@ -587,7 +587,7 @@ lpfc_gen_req(struct lpfc_vport *vport, s
Daniel Wagner 546e11
 	     struct lpfc_dmabuf *inp, struct lpfc_dmabuf *outp,
Daniel Wagner 546e11
 	     void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
Daniel Wagner 546e11
 		     struct lpfc_iocbq *),
Daniel Wagner 546e11
-	     struct lpfc_nodelist *ndlp, uint32_t usr_flg, uint32_t num_entry,
Daniel Wagner 546e11
+	     struct lpfc_nodelist *ndlp, uint32_t event_tag, uint32_t num_entry,
Daniel Wagner 546e11
 	     uint32_t tmo, uint8_t retry)
Daniel Wagner 546e11
 {
Daniel Wagner 546e11
 	struct lpfc_hba  *phba = vport->phba;
Daniel Wagner 546e11
@@ -608,15 +608,14 @@ lpfc_gen_req(struct lpfc_vport *vport, s
Daniel Wagner 546e11
 	icmd->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
Daniel Wagner 546e11
 	icmd->un.genreq64.bdl.bdeSize = (num_entry * sizeof(struct ulp_bde64));
Daniel Wagner 546e11
 
Daniel Wagner 546e11
-	if (usr_flg)
Daniel Wagner 546e11
-		geniocb->context3 = NULL;
Daniel Wagner 546e11
-	else
Daniel Wagner 546e11
-		geniocb->context3 = (uint8_t *) bmp;
Daniel Wagner 546e11
+	geniocb->context3 = (uint8_t *) bmp;
Daniel Wagner 546e11
 
Daniel Wagner 546e11
 	/* Save for completion so we can release these resources */
Daniel Wagner 546e11
 	geniocb->context1 = (uint8_t *) inp;
Daniel Wagner 546e11
 	geniocb->context2 = (uint8_t *) outp;
Daniel Wagner 546e11
 
Daniel Wagner 546e11
+	geniocb->event_tag = event_tag;
Daniel Wagner 546e11
+
Daniel Wagner 546e11
 	/* Fill in payload, bp points to frame payload */
Daniel Wagner 546e11
 	icmd->ulpCommand = CMD_GEN_REQUEST64_CR;
Daniel Wagner 546e11
 
Daniel Wagner 546e11
@@ -707,8 +706,8 @@ lpfc_ct_cmd(struct lpfc_vport *vport, st
Daniel Wagner 546e11
 	 * lpfc_alloc_ct_rsp.
Daniel Wagner 546e11
 	 */
Daniel Wagner 546e11
 	cnt += 1;
Daniel Wagner 546e11
-	status = lpfc_gen_req(vport, bmp, inmp, outmp, cmpl, ndlp, 0,
Daniel Wagner 546e11
-			      cnt, 0, retry);
Daniel Wagner 546e11
+	status = lpfc_gen_req(vport, bmp, inmp, outmp, cmpl, ndlp,
Daniel Wagner 546e11
+			phba->fc_eventTag, cnt, 0, retry);
Daniel Wagner 546e11
 	if (status) {
Daniel Wagner 546e11
 		lpfc_free_ct_rsp(phba, outmp);
Daniel Wagner 546e11
 		return -ENOMEM;
Daniel Wagner 546e11
@@ -957,6 +956,13 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba
Daniel Wagner 546e11
 		 "GID_FT cmpl:     status:x%x/x%x rtry:%d",
Daniel Wagner 546e11
 		irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_ns_retry);
Daniel Wagner 546e11
 
Daniel Wagner 546e11
+	/* Ignore response if link flipped after this request was made */
Daniel Wagner 546e11
+	if (cmdiocb->event_tag != phba->fc_eventTag) {
Daniel Wagner 546e11
+		lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
Daniel Wagner 546e11
+				 "9043 Event tag mismatch. Ignoring NS rsp\n");
Daniel Wagner 546e11
+		goto out;
Daniel Wagner 546e11
+	}
Daniel Wagner 546e11
+
Daniel Wagner 546e11
 	/* Don't bother processing response if vport is being torn down. */
Daniel Wagner 546e11
 	if (vport->load_flag & FC_UNLOADING) {
Daniel Wagner 546e11
 		if (vport->fc_flag & FC_RSCN_MODE)
Daniel Wagner 546e11
@@ -1167,6 +1173,13 @@ lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba
Daniel Wagner 546e11
 			      irsp->ulpStatus, irsp->un.ulpWord[4],
Daniel Wagner 546e11
 			      vport->fc_ns_retry);
Daniel Wagner 546e11
 
Daniel Wagner 546e11
+	/* Ignore response if link flipped after this request was made */
Daniel Wagner 546e11
+	if (cmdiocb->event_tag != phba->fc_eventTag) {
Daniel Wagner 546e11
+		lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
Daniel Wagner 546e11
+				 "9044 Event tag mismatch. Ignoring NS rsp\n");
Daniel Wagner 546e11
+		goto out;
Daniel Wagner 546e11
+	}
Daniel Wagner 546e11
+
Daniel Wagner 546e11
 	/* Don't bother processing response if vport is being torn down. */
Daniel Wagner 546e11
 	if (vport->load_flag & FC_UNLOADING) {
Daniel Wagner 546e11
 		if (vport->fc_flag & FC_RSCN_MODE)
Daniel Wagner 546e11
@@ -1366,6 +1379,13 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba
Daniel Wagner 546e11
 		"GFF_ID cmpl:     status:x%x/x%x did:x%x",
Daniel Wagner 546e11
 		irsp->ulpStatus, irsp->un.ulpWord[4], did);
Daniel Wagner 546e11
 
Daniel Wagner 546e11
+	/* Ignore response if link flipped after this request was made */
Daniel Wagner 546e11
+	if (cmdiocb->event_tag != phba->fc_eventTag) {
Daniel Wagner 546e11
+		lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
Daniel Wagner 546e11
+				 "9045 Event tag mismatch. Ignoring NS rsp\n");
Daniel Wagner 546e11
+		goto iocb_free;
Daniel Wagner 546e11
+	}
Daniel Wagner 546e11
+
Daniel Wagner 546e11
 	if (irsp->ulpStatus == IOSTAT_SUCCESS) {
Daniel Wagner 546e11
 		/* Good status, continue checking */
Daniel Wagner 546e11
 		CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
Daniel Wagner 546e11
@@ -1479,6 +1499,7 @@ lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba
Daniel Wagner 546e11
 		lpfc_disc_start(vport);
Daniel Wagner 546e11
 	}
Daniel Wagner 546e11
 
Daniel Wagner 546e11
+iocb_free:
Daniel Wagner 546e11
 	free_ndlp = cmdiocb->context_un.ndlp;
Daniel Wagner 546e11
 	lpfc_ct_free_iocb(phba, cmdiocb);
Daniel Wagner 546e11
 	lpfc_nlp_put(free_ndlp);
Daniel Wagner 546e11
@@ -1506,6 +1527,13 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba
Daniel Wagner 546e11
 			      "GFT_ID cmpl: status:x%x/x%x did:x%x",
Daniel Wagner 546e11
 			      irsp->ulpStatus, irsp->un.ulpWord[4], did);
Daniel Wagner 546e11
 
Daniel Wagner 546e11
+	/* Ignore response if link flipped after this request was made */
Daniel Wagner 546e11
+	if ((uint32_t) cmdiocb->event_tag != phba->fc_eventTag) {
Daniel Wagner 546e11
+		lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
Daniel Wagner 546e11
+				 "9046 Event tag mismatch. Ignoring NS rsp\n");
Daniel Wagner 546e11
+		goto out;
Daniel Wagner 546e11
+	}
Daniel Wagner 546e11
+
Daniel Wagner 546e11
 	/* Preserve the nameserver node to release the reference. */
Daniel Wagner 546e11
 	ns_ndlp = cmdiocb->context_un.ndlp;
Daniel Wagner 546e11
 
Daniel Wagner 546e11
@@ -1572,6 +1600,7 @@ lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba
Daniel Wagner 546e11
 		lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
Daniel Wagner 546e11
 				 "3065 GFT_ID failed x%08x\n", irsp->ulpStatus);
Daniel Wagner 546e11
 
Daniel Wagner 546e11
+out:
Daniel Wagner 546e11
 	lpfc_ct_free_iocb(phba, cmdiocb);
Daniel Wagner 546e11
 	lpfc_nlp_put(ns_ndlp);
Daniel Wagner 546e11
 }
Daniel Wagner 546e11
--- a/drivers/scsi/lpfc/lpfc_sli.h
Daniel Wagner 546e11
+++ b/drivers/scsi/lpfc/lpfc_sli.h
Daniel Wagner 546e11
@@ -1,7 +1,7 @@
Daniel Wagner 546e11
 /*******************************************************************
Daniel Wagner 546e11
  * This file is part of the Emulex Linux Device Driver for         *
Daniel Wagner 546e11
  * Fibre Channel Host Bus Adapters.                                *
Daniel Wagner 546e11
- * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term *
Daniel Wagner 546e11
+ * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term *
Daniel Wagner 546e11
  * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.     *
Daniel Wagner 546e11
  * Copyright (C) 2004-2016 Emulex.  All rights reserved.           *
Daniel Wagner 546e11
  * EMULEX and SLI are trademarks of Emulex.                        *
Daniel Wagner 546e11
@@ -106,6 +106,7 @@ struct lpfc_iocbq {
Daniel Wagner 546e11
 	void *context1;		/* caller context information */
Daniel Wagner 546e11
 	void *context2;		/* caller context information */
Daniel Wagner 546e11
 	void *context3;		/* caller context information */
Daniel Wagner 546e11
+	uint32_t event_tag;	/* LA Event tag */
Daniel Wagner 546e11
 	union {
Daniel Wagner 546e11
 		wait_queue_head_t    *wait_queue;
Daniel Wagner 546e11
 		struct lpfc_iocbq    *rsp_iocb;