Commit 5b5dedf0 authored by Martin K. Petersen's avatar Martin K. Petersen
Browse files

Merge patch series "Update lpfc to revision 14.4.0.12"

Justin Tee <justin.tee@broadcom.com> says:

Update lpfc to revision 14.4.0.12

This patch set contains updates to log messaging, revision of outdated
comment descriptions, fixes to kref accounting, support for BB credit
recovery in point-to-point mode, and introduction of registering unique
platform name identifiers with fabrics.

The patches were cut against Martin's 6.19/scsi-queue tree.

Link: https://patch.msgid.link/20251106224639.139176-1-justintee8345@gmail.com


Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parents e1571024 d45fdc6c
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -311,7 +311,6 @@ struct lpfc_defer_flogi_acc {
	u16 rx_id;
	u16 ox_id;
	struct lpfc_nodelist *ndlp;

};

#define LPFC_VMID_TIMER   300	/* timer interval in seconds */
@@ -634,6 +633,7 @@ struct lpfc_vport {
#define FC_CT_RSPN_ID		0x8	 /* RSPN_ID accepted by switch */
#define FC_CT_RFT_ID		0x10	 /* RFT_ID accepted by switch */
#define FC_CT_RPRT_DEFER	0x20	 /* Defer issuing FDMI RPRT */
#define FC_CT_RSPNI_PNI		0x40	 /* RSPNI_PNI accepted by switch */

	struct list_head fc_nodes;
	spinlock_t fc_nodes_list_lock; /* spinlock for fc_nodes list */
@@ -1078,6 +1078,8 @@ struct lpfc_hba {

	uint32_t nport_event_cnt;	/* timestamp for nlplist entry */

	unsigned long pni;		/* 64-bit Platform Name Identifier */

	uint8_t  wwnn[8];
	uint8_t  wwpn[8];
	uint32_t RandomData[7];
+36 −0
Original line number Diff line number Diff line
@@ -1742,6 +1742,28 @@ lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
	return;
}

static void
lpfc_cmpl_ct_cmd_rspni_pni(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
			   struct lpfc_iocbq *rspiocb)
{
	struct lpfc_vport *vport;
	struct lpfc_dmabuf *outp;
	struct lpfc_sli_ct_request *ctrsp;
	u32 ulp_status;

	vport = cmdiocb->vport;
	ulp_status = get_job_ulpstatus(phba, rspiocb);

	if (ulp_status == IOSTAT_SUCCESS) {
		outp = cmdiocb->rsp_dmabuf;
		ctrsp = (struct lpfc_sli_ct_request *)outp->virt;
		if (be16_to_cpu(ctrsp->CommandResponse.bits.CmdRsp) ==
		    SLI_CT_RESPONSE_FS_ACC)
			vport->ct_flags |= FC_CT_RSPNI_PNI;
	}
	lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
}

static void
lpfc_cmpl_ct_cmd_da_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 struct lpfc_iocbq *rspiocb)
@@ -1956,6 +1978,8 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
		bpl->tus.f.bdeSize = RSPN_REQUEST_SZ;
	else if (cmdcode == SLI_CTNS_RSNN_NN)
		bpl->tus.f.bdeSize = RSNN_REQUEST_SZ;
	else if (cmdcode == SLI_CTNS_RSPNI_PNI)
		bpl->tus.f.bdeSize = RSPNI_REQUEST_SZ;
	else if (cmdcode == SLI_CTNS_DA_ID)
		bpl->tus.f.bdeSize = DA_ID_REQUEST_SZ;
	else if (cmdcode == SLI_CTNS_RFF_ID)
@@ -2077,6 +2101,18 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
			CtReq->un.rsnn.symbname, size);
		cmpl = lpfc_cmpl_ct_cmd_rsnn_nn;
		break;
	case SLI_CTNS_RSPNI_PNI:
		vport->ct_flags &= ~FC_CT_RSPNI_PNI;
		CtReq->CommandResponse.bits.CmdRsp =
		    cpu_to_be16(SLI_CTNS_RSPNI_PNI);
		CtReq->un.rspni.pni = cpu_to_be64(phba->pni);
		scnprintf(CtReq->un.rspni.symbname,
			  sizeof(CtReq->un.rspni.symbname), "OS Host Name::%s",
			  phba->os_host_name);
		CtReq->un.rspni.len = strnlen(CtReq->un.rspni.symbname,
					      sizeof(CtReq->un.rspni.symbname));
		cmpl = lpfc_cmpl_ct_cmd_rspni_pni;
		break;
	case SLI_CTNS_DA_ID:
		/* Implement DA_ID Nameserver request */
		CtReq->CommandResponse.bits.CmdRsp =
+2 −1
Original line number Diff line number Diff line
/*******************************************************************
 * This file is part of the Emulex Linux Device Driver for         *
 * Fibre Channel Host Bus Adapters.                                *
 * Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
 * Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.     *
 * Copyright (C) 2004-2013 Emulex.  All rights reserved.           *
 * EMULEX and SLI are trademarks of Emulex.                        *
@@ -208,6 +208,7 @@ enum lpfc_nlp_flag {
					   NPR list */
	NLP_RM_DFLT_RPI    = 26,        /* need to remove leftover dflt RPI */
	NLP_NODEV_REMOVE   = 27,        /* Defer removal till discovery ends */
	NLP_FLOGI_DFR_ACC  = 28,        /* FLOGI LS_ACC was Deferred */
	NLP_SC_REQ         = 29,        /* Target requires authentication */
	NLP_FIRSTBURST     = 30,        /* Target supports FirstBurst */
	NLP_RPI_REGISTERED = 31         /* nlp_rpi is valid */
+174 −75
Original line number Diff line number Diff line
@@ -650,8 +650,6 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
		ndlp->nlp_class_sup |= FC_COS_CLASS2;
	if (sp->cls3.classValid)
		ndlp->nlp_class_sup |= FC_COS_CLASS3;
	if (sp->cls4.classValid)
		ndlp->nlp_class_sup |= FC_COS_CLASS4;
	ndlp->nlp_maxframe = ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) |
				sp->cmn.bbRcvSizeLsb;

@@ -934,10 +932,15 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
	/* Check to see if link went down during discovery */
	if (lpfc_els_chk_latt(vport)) {
		/* One additional decrement on node reference count to
		 * trigger the release of the node
		 * trigger the release of the node.  Make sure the ndlp
		 * is marked NLP_DROPPED.
		 */
		if (!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD))
		if (!test_bit(NLP_IN_DEV_LOSS, &ndlp->nlp_flag) &&
		    !test_bit(NLP_DROPPED, &ndlp->nlp_flag) &&
		    !(ndlp->fc4_xpt_flags & SCSI_XPT_REGD)) {
			set_bit(NLP_DROPPED, &ndlp->nlp_flag);
			lpfc_nlp_put(ndlp);
		}
		goto out;
	}

@@ -995,9 +998,10 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
					IOERR_LOOP_OPEN_FAILURE)))
			lpfc_vlog_msg(vport, KERN_WARNING, LOG_ELS,
				      "2858 FLOGI Status:x%x/x%x TMO"
				      ":x%x Data x%lx x%x\n",
				      ":x%x Data x%lx x%x x%lx x%x\n",
				      ulp_status, ulp_word4, tmo,
				      phba->hba_flag, phba->fcf.fcf_flag);
				      phba->hba_flag, phba->fcf.fcf_flag,
				      ndlp->nlp_flag, ndlp->fc4_xpt_flags);

		/* Check for retry */
		if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
@@ -1015,14 +1019,17 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
		 * reference to trigger node release.
		 */
		if (!test_bit(NLP_IN_DEV_LOSS, &ndlp->nlp_flag) &&
		    !(ndlp->fc4_xpt_flags & SCSI_XPT_REGD))
		    !test_bit(NLP_DROPPED, &ndlp->nlp_flag) &&
		    !(ndlp->fc4_xpt_flags & SCSI_XPT_REGD)) {
			set_bit(NLP_DROPPED, &ndlp->nlp_flag);
			lpfc_nlp_put(ndlp);
		}

		lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS,
				 "0150 FLOGI Status:x%x/x%x "
				 "xri x%x TMO:x%x refcnt %d\n",
				 "xri x%x iotag x%x TMO:x%x refcnt %d\n",
				 ulp_status, ulp_word4, cmdiocb->sli4_xritag,
				 tmo, kref_read(&ndlp->kref));
				 cmdiocb->iotag, tmo, kref_read(&ndlp->kref));

		/* If this is not a loop open failure, bail out */
		if (!(ulp_status == IOSTAT_LOCAL_REJECT &&
@@ -1279,6 +1286,19 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
	uint32_t tmo, did;
	int rc;

	/* It's possible for lpfc to reissue a FLOGI on an ndlp that is marked
	 * NLP_DROPPED.  This happens when the FLOGI completed with the XB bit
	 * set causing lpfc to reference the ndlp until the XRI_ABORTED CQE is
	 * issued. The time window for the XRI_ABORTED CQE can be as much as
	 * 2*2*RA_TOV allowing for ndlp reuse of this type when the link is
	 * cycling quickly.  When true, restore the initial reference and remove
	 * the NLP_DROPPED flag as lpfc is retrying.
	 */
	if (test_and_clear_bit(NLP_DROPPED, &ndlp->nlp_flag)) {
		if (!lpfc_nlp_get(ndlp))
			return 1;
	}

	cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
	elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
				     ndlp->nlp_DID, ELS_CMD_FLOGI);
@@ -1334,6 +1354,14 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
		/* Can't do SLI4 class2 without support sequence coalescing */
		sp->cls2.classValid = 0;
		sp->cls2.seqDelivery = 0;

		/* Fill out Auxiliary Parameter Data */
		if (phba->pni) {
			sp->aux.flags =
				AUX_PARM_DATA_VALID | AUX_PARM_PNI_VALID;
			sp->aux.pni = cpu_to_be64(phba->pni);
			sp->aux.npiv_cnt = cpu_to_be16(phba->max_vpi - 1);
		}
	} else {
		/* Historical, setting sequential-delivery bit for SLI3 */
		sp->cls2.seqDelivery = (sp->cls2.classValid) ? 1 : 0;
@@ -1413,11 +1441,12 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
				phba->defer_flogi_acc.ox_id;
		}

		lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
				 "3354 Xmit deferred FLOGI ACC: rx_id: x%x,"
				 " ox_id: x%x, hba_flag x%lx\n",
				 phba->defer_flogi_acc.rx_id,
				 phba->defer_flogi_acc.ox_id, phba->hba_flag);
		/* The LS_ACC completion needs to drop the initial reference.
		 * This is a special case for Pt2Pt because both FLOGIs need
		 * to complete and lpfc defers the LS_ACC when the remote
		 * FLOGI arrives before the driver's FLOGI.
		 */
		set_bit(NLP_FLOGI_DFR_ACC, &ndlp->nlp_flag);

		/* Send deferred FLOGI ACC */
		lpfc_els_rsp_acc(vport, ELS_CMD_FLOGI, &defer_flogi_acc,
@@ -1433,6 +1462,14 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
			phba->defer_flogi_acc.ndlp = NULL;
		}

		lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
				 "3354 Xmit deferred FLOGI ACC: rx_id: x%x,"
				 " ox_id: x%x, ndlp x%px hba_flag x%lx\n",
				 phba->defer_flogi_acc.rx_id,
				 phba->defer_flogi_acc.ox_id,
				 phba->defer_flogi_acc.ndlp,
				 phba->hba_flag);

		vport->fc_myDID = did;
	}

@@ -2248,6 +2285,7 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)

	sp->cmn.valid_vendor_ver_level = 0;
	memset(sp->un.vendorVersion, 0, sizeof(sp->un.vendorVersion));
	if (!test_bit(FC_PT2PT, &vport->fc_flag))
		sp->cmn.bbRcvSizeMsb &= 0xF;

	/* Check if the destination port supports VMID */
@@ -2367,7 +2405,7 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
			mode = KERN_INFO;

		/* Warn PRLI status */
		lpfc_printf_vlog(vport, mode, LOG_ELS,
		lpfc_vlog_msg(vport, mode, LOG_ELS,
				 "2754 PRLI DID:%06X Status:x%x/x%x, "
				 "data: x%x x%x x%lx\n",
				 ndlp->nlp_DID, ulp_status,
@@ -3024,6 +3062,7 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
			      ndlp->nlp_DID, ulp_status,
			      ulp_word4);

		/* Call NLP_EVT_DEVICE_RM if link is down or LOGO is aborted */
		if (lpfc_error_lost_link(vport, ulp_status, ulp_word4))
			skip_recovery = 1;
	}
@@ -3262,7 +3301,7 @@ lpfc_reg_fab_ctrl_node(struct lpfc_vport *vport, struct lpfc_nodelist *fc_ndlp)
		return -ENOMEM;
	}
	rc = lpfc_reg_rpi(phba, vport->vpi, fc_ndlp->nlp_DID,
			  (u8 *)&vport->fc_sparam, mbox, fc_ndlp->nlp_rpi);
			  (u8 *)&ns_ndlp->fc_sparam, mbox, fc_ndlp->nlp_rpi);
	if (rc) {
		rc = -EACCES;
		goto out;
@@ -3306,7 +3345,8 @@ lpfc_reg_fab_ctrl_node(struct lpfc_vport *vport, struct lpfc_nodelist *fc_ndlp)
 *
 * This routine is a generic completion callback function for Discovery ELS cmd.
 * Currently used by the ELS command issuing routines for the ELS State Change
 * Request (SCR), lpfc_issue_els_scr() and the ELS RDF, lpfc_issue_els_rdf().
 * Request (SCR), lpfc_issue_els_scr(), Exchange Diagnostic Capabilities (EDC),
 * lpfc_issue_els_edc()  and the ELS RDF, lpfc_issue_els_rdf().
 * These commands will be retried once only for ELS timeout errors.
 **/
static void
@@ -3379,11 +3419,21 @@ lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
		lpfc_cmpl_els_edc(phba, cmdiocb, rspiocb);
		return;
	}

	if (ulp_status) {
		/* ELS discovery cmd completes with error */
		lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS | LOG_CGN_MGMT,
				 "4203 ELS cmd x%x error: x%x x%X\n", cmd,
				 ulp_status, ulp_word4);

		/* In the case where the ELS cmd completes with an error and
		 * the node does not have RPI registered, the node is
		 * outstanding and should put its initial reference.
		 */
		if ((cmd == ELS_CMD_SCR || cmd == ELS_CMD_RDF) &&
		    !(ndlp->fc4_xpt_flags & SCSI_XPT_REGD) &&
		    !test_and_set_bit(NLP_DROPPED, &ndlp->nlp_flag))
			lpfc_nlp_put(ndlp);
		goto out;
	}

@@ -3452,6 +3502,7 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
	uint8_t *pcmd;
	uint16_t cmdsize;
	struct lpfc_nodelist *ndlp;
	bool node_created = false;

	cmdsize = (sizeof(uint32_t) + sizeof(SCR));

@@ -3461,21 +3512,21 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
		if (!ndlp)
			return 1;
		lpfc_enqueue_node(vport, ndlp);
		node_created = true;
	}

	elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
				     ndlp->nlp_DID, ELS_CMD_SCR);
	if (!elsiocb)
		return 1;
		goto out_node_created;

	if (phba->sli_rev == LPFC_SLI_REV4) {
		rc = lpfc_reg_fab_ctrl_node(vport, ndlp);
		if (rc) {
			lpfc_els_free_iocb(phba, elsiocb);
			lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
					 "0937 %s: Failed to reg fc node, rc %d\n",
					 __func__, rc);
			return 1;
			goto out_free_iocb;
		}
	}
	pcmd = (uint8_t *)elsiocb->cmd_dmabuf->virt;
@@ -3494,25 +3545,29 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
	phba->fc_stat.elsXmitSCR++;
	elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd;
	elsiocb->ndlp = lpfc_nlp_get(ndlp);
	if (!elsiocb->ndlp) {
		lpfc_els_free_iocb(phba, elsiocb);
		return 1;
	}
	if (!elsiocb->ndlp)
		goto out_free_iocb;

	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
			      "Issue SCR:     did:x%x refcnt %d",
			      ndlp->nlp_DID, kref_read(&ndlp->kref), 0);

	rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
	if (rc == IOCB_ERROR) {
	if (rc == IOCB_ERROR)
		goto out_iocb_error;

	return 0;

out_iocb_error:
	lpfc_nlp_put(ndlp);
out_free_iocb:
	lpfc_els_free_iocb(phba, elsiocb);
out_node_created:
	if (node_created)
		lpfc_nlp_put(ndlp);
	return 1;
}

	return 0;
}

/**
 * lpfc_issue_els_rscn - Issue an RSCN to the Fabric Controller (Fabric)
 *   or the other nport (pt2pt).
@@ -3597,8 +3652,8 @@ lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry)
	}

	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
			      "Issue RSCN:       did:x%x",
			      ndlp->nlp_DID, 0, 0);
			      "Issue RSCN:   did:x%x refcnt %d",
			      ndlp->nlp_DID, kref_read(&ndlp->kref), 0);

	rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
	if (rc == IOCB_ERROR) {
@@ -3705,10 +3760,7 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
		lpfc_nlp_put(ndlp);
		return 1;
	}
	/* This will cause the callback-function lpfc_cmpl_els_cmd to
	 * trigger the release of the node.
	 */
	/* Don't release reference count as RDF is likely outstanding */

	return 0;
}

@@ -3726,7 +3778,12 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
 *
 * Return code
 *   0 - Successfully issued rdf command
 *   1 - Failed to issue rdf command
 *   < 0 - Failed to issue rdf command
 *   -EACCES - RDF not required for NPIV_PORT
 *   -ENODEV - No fabric controller device available
 *   -ENOMEM - No available memory
 *   -EIO - The mailbox failed to complete successfully.
 *
 **/
int
lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
@@ -3737,25 +3794,30 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
	struct lpfc_nodelist *ndlp;
	uint16_t cmdsize;
	int rc;
	bool node_created = false;
	int err;

	cmdsize = sizeof(*prdf);

	/* RDF ELS is not required on an NPIV VN_Port. */
	if (vport->port_type == LPFC_NPIV_PORT)
		return -EACCES;

	ndlp = lpfc_findnode_did(vport, Fabric_Cntl_DID);
	if (!ndlp) {
		ndlp = lpfc_nlp_init(vport, Fabric_Cntl_DID);
		if (!ndlp)
			return -ENODEV;
		lpfc_enqueue_node(vport, ndlp);
		node_created = true;
	}

	/* RDF ELS is not required on an NPIV VN_Port. */
	if (vport->port_type == LPFC_NPIV_PORT)
		return -EACCES;

	elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
				     ndlp->nlp_DID, ELS_CMD_RDF);
	if (!elsiocb)
		return -ENOMEM;
	if (!elsiocb) {
		err = -ENOMEM;
		goto out_node_created;
	}

	/* Configure the payload for the supported FPIN events. */
	prdf = (struct lpfc_els_rdf_req *)elsiocb->cmd_dmabuf->virt;
@@ -3781,8 +3843,8 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
	elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd;
	elsiocb->ndlp = lpfc_nlp_get(ndlp);
	if (!elsiocb->ndlp) {
		lpfc_els_free_iocb(phba, elsiocb);
		return -EIO;
		err = -EIO;
		goto out_free_iocb;
	}

	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
@@ -3791,11 +3853,19 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)

	rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
	if (rc == IOCB_ERROR) {
		lpfc_els_free_iocb(phba, elsiocb);
		lpfc_nlp_put(ndlp);
		return -EIO;
		err = -EIO;
		goto out_iocb_error;
	}
	return 0;

out_iocb_error:
	lpfc_nlp_put(ndlp);
out_free_iocb:
	lpfc_els_free_iocb(phba, elsiocb);
out_node_created:
	if (node_created)
		lpfc_nlp_put(ndlp);
	return err;
}

 /**
@@ -3816,19 +3886,23 @@ static int
lpfc_els_rcv_rdf(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
		 struct lpfc_nodelist *ndlp)
{
	int rc;

	rc = lpfc_els_rsp_acc(vport, ELS_CMD_RDF, cmdiocb, ndlp, NULL);
	/* Send LS_ACC */
	if (lpfc_els_rsp_acc(vport, ELS_CMD_RDF, cmdiocb, ndlp, NULL)) {
	if (rc) {
		lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
				 "1623 Failed to RDF_ACC from x%x for x%x\n",
				 ndlp->nlp_DID, vport->fc_myDID);
				 "1623 Failed to RDF_ACC from x%x for x%x Data: %d\n",
				 ndlp->nlp_DID, vport->fc_myDID, rc);
		return -EIO;
	}

	rc = lpfc_issue_els_rdf(vport, 0);
	/* Issue new RDF for reregistering */
	if (lpfc_issue_els_rdf(vport, 0)) {
	if (rc) {
		lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
				 "2623 Failed to re register RDF for x%x\n",
				 vport->fc_myDID);
				 "2623 Failed to re register RDF for x%x Data: %d\n",
				 vport->fc_myDID, rc);
		return -EIO;
	}

@@ -4299,7 +4373,7 @@ lpfc_issue_els_edc(struct lpfc_vport *vport, uint8_t retry)
	rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
	if (rc == IOCB_ERROR) {
		/* The additional lpfc_nlp_put will cause the following
		 * lpfc_els_free_iocb routine to trigger the rlease of
		 * lpfc_els_free_iocb routine to trigger the release of
		 * the node.
		 */
		lpfc_els_free_iocb(phba, elsiocb);
@@ -5127,7 +5201,7 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
{
	struct lpfc_dmabuf *buf_ptr, *buf_ptr1;

	/* The I/O iocb is complete.  Clear the node and first dmbuf */
	/* The I/O iocb is complete.  Clear the node and first dmabuf */
	elsiocb->ndlp = NULL;

	/* cmd_dmabuf = cmd,  cmd_dmabuf->next = rsp, bpl_dmabuf = bpl */
@@ -5160,14 +5234,12 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
		} else {
			buf_ptr1 = elsiocb->cmd_dmabuf;
			lpfc_els_free_data(phba, buf_ptr1);
			elsiocb->cmd_dmabuf = NULL;
		}
	}

	if (elsiocb->bpl_dmabuf) {
		buf_ptr = elsiocb->bpl_dmabuf;
		lpfc_els_free_bpl(phba, buf_ptr);
		elsiocb->bpl_dmabuf = NULL;
	}
	lpfc_sli_release_iocbq(phba, elsiocb);
	return 0;
@@ -5305,11 +5377,12 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
	IOCB_t  *irsp;
	LPFC_MBOXQ_t *mbox = NULL;
	u32 ulp_status, ulp_word4, tmo, did, iotag;
	u32 cmd;

	if (!vport) {
		lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
				"3177 null vport in ELS rsp\n");
		goto out;
		goto release;
	}
	if (cmdiocb->context_un.mbox)
		mbox = cmdiocb->context_un.mbox;
@@ -5419,7 +5492,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
	 * these conditions because it doesn't need the login.
	 */
	if (phba->sli_rev == LPFC_SLI_REV4 &&
	    vport && vport->port_type == LPFC_NPIV_PORT &&
	    vport->port_type == LPFC_NPIV_PORT &&
	    !(ndlp->fc4_xpt_flags & SCSI_XPT_REGD)) {
		if (ndlp->nlp_state != NLP_STE_PLOGI_ISSUE &&
		    ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE &&
@@ -5435,6 +5508,27 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
		}
	}

	/* The driver's unsolicited deferred FLOGI ACC in Pt2Pt needs to
	 * release the initial reference because the put after the free_iocb
	 * call removes only the reference from the defer logic. This FLOGI
	 * is never registered with the SCSI transport.
	 */
	if (test_bit(FC_PT2PT, &vport->fc_flag) &&
	    test_and_clear_bit(NLP_FLOGI_DFR_ACC, &ndlp->nlp_flag)) {
		lpfc_printf_vlog(vport, KERN_INFO,
				 LOG_ELS | LOG_NODE | LOG_DISCOVERY,
				 "3357 Pt2Pt Defer FLOGI ACC ndlp x%px, "
				 "nflags x%lx, fc_flag x%lx\n",
				 ndlp, ndlp->nlp_flag,
				 vport->fc_flag);
		cmd = *((u32 *)cmdiocb->cmd_dmabuf->virt);
		if (cmd == ELS_CMD_ACC) {
			if (!test_and_set_bit(NLP_DROPPED, &ndlp->nlp_flag))
				lpfc_nlp_put(ndlp);
		}
	}

release:
	/* Release the originating I/O reference. */
	lpfc_els_free_iocb(phba, cmdiocb);
	lpfc_nlp_put(ndlp);
@@ -5569,7 +5663,6 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
			sp->cls1.classValid = 0;
			sp->cls2.classValid = 0;
			sp->cls3.classValid = 0;
			sp->cls4.classValid = 0;

			/* Copy our worldwide names */
			memcpy(&sp->portName, &vport->fc_sparam.portName,
@@ -5583,6 +5676,7 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
			sp->cmn.valid_vendor_ver_level = 0;
			memset(sp->un.vendorVersion, 0,
			       sizeof(sp->un.vendorVersion));
			if (!test_bit(FC_PT2PT, &vport->fc_flag))
				sp->cmn.bbRcvSizeMsb &= 0xF;

			/* If our firmware supports this feature, convey that
@@ -8402,13 +8496,6 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
						     &wqe->xmit_els_rsp.wqe_com);

		vport->fc_myDID = did;

		lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
				 "3344 Deferring FLOGI ACC: rx_id: x%x,"
				 " ox_id: x%x, hba_flag x%lx\n",
				 phba->defer_flogi_acc.rx_id,
				 phba->defer_flogi_acc.ox_id, phba->hba_flag);

		phba->defer_flogi_acc.flag = true;

		/* This nlp_get is paired with nlp_puts that reset the
@@ -8417,6 +8504,14 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
		 * processed or cancelled.
		 */
		phba->defer_flogi_acc.ndlp = lpfc_nlp_get(ndlp);

		lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
				 "3344 Deferring FLOGI ACC: rx_id: x%x,"
				 " ox_id: x%x, ndlp x%px, hba_flag x%lx\n",
				 phba->defer_flogi_acc.rx_id,
				 phba->defer_flogi_acc.ox_id,
				 phba->defer_flogi_acc.ndlp,
				 phba->hba_flag);
		return 0;
	}

@@ -8734,7 +8829,7 @@ lpfc_els_rcv_rls(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
 * @cmdiocb: pointer to lpfc command iocb data structure.
 * @ndlp: pointer to a node-list data structure.
 *
 * This routine processes Read Timout Value (RTV) IOCB received as an
 * This routine processes Read Timeout Value (RTV) IOCB received as an
 * ELS unsolicited event. It first checks the remote port state. If the
 * remote port is not in NLP_STE_UNMAPPED_NODE state or NLP_STE_MAPPED_NODE
 * state, it invokes the lpfc_els_rsl_reject() routine to send the reject
@@ -10357,11 +10452,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
	 * Do not process any unsolicited ELS commands
	 * if the ndlp is in DEV_LOSS
	 */
	if (test_bit(NLP_IN_DEV_LOSS, &ndlp->nlp_flag)) {
		if (newnode)
			lpfc_nlp_put(ndlp);
	if (test_bit(NLP_IN_DEV_LOSS, &ndlp->nlp_flag))
		goto dropit;
	}

	elsiocb->ndlp = lpfc_nlp_get(ndlp);
	if (!elsiocb->ndlp)
@@ -10843,7 +10935,7 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
	lpfc_els_unsol_buffer(phba, pring, vport, elsiocb);
	/*
	 * The different unsolicited event handlers would tell us
	 * if they are done with "mp" by setting cmd_dmabuf to NULL.
	 * if they are done with "mp" by setting cmd_dmabuf/bpl_dmabuf to NULL.
	 */
	if (elsiocb->cmd_dmabuf) {
		lpfc_in_buf_free(phba, elsiocb->cmd_dmabuf);
@@ -11423,6 +11515,13 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
	sp->cls2.seqDelivery = 1;
	sp->cls3.seqDelivery = 1;

	/* Fill out Auxiliary Parameter Data */
	if (phba->pni) {
		sp->aux.flags =
			AUX_PARM_DATA_VALID | AUX_PARM_PNI_VALID;
		sp->aux.pni = cpu_to_be64(phba->pni);
	}

	pcmd += sizeof(uint32_t); /* CSP Word 2 */
	pcmd += sizeof(uint32_t); /* CSP Word 3 */
	pcmd += sizeof(uint32_t); /* CSP Word 4 */
+5 −1
Original line number Diff line number Diff line
@@ -424,6 +424,7 @@ lpfc_check_nlp_post_devloss(struct lpfc_vport *vport,
			    struct lpfc_nodelist *ndlp)
{
	if (test_and_clear_bit(NLP_IN_RECOV_POST_DEV_LOSS, &ndlp->save_flags)) {
		clear_bit(NLP_DROPPED, &ndlp->nlp_flag);
		lpfc_nlp_get(ndlp);
		lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY | LOG_NODE,
				 "8438 Devloss timeout reversed on DID x%x "
@@ -566,6 +567,7 @@ lpfc_dev_loss_tmo_handler(struct lpfc_nodelist *ndlp)
			return fcf_inuse;
		}

		if (!test_and_set_bit(NLP_DROPPED, &ndlp->nlp_flag))
			lpfc_nlp_put(ndlp);
		return fcf_inuse;
	}
@@ -4371,6 +4373,8 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
		lpfc_ns_cmd(vport, SLI_CTNS_RNN_ID, 0, 0);
		lpfc_ns_cmd(vport, SLI_CTNS_RSNN_NN, 0, 0);
		lpfc_ns_cmd(vport, SLI_CTNS_RSPN_ID, 0, 0);
		if (phba->pni)
			lpfc_ns_cmd(vport, SLI_CTNS_RSPNI_PNI, 0, 0);
		lpfc_ns_cmd(vport, SLI_CTNS_RFT_ID, 0, 0);

		if ((vport->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) ||
Loading