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