Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7c5e518c authored by James Smart's avatar James Smart Committed by James Bottomley
Browse files

lpfc: Fix to drop PLOGIs from fabric node till LOGO processing completes



The domain controller PLOGI's concurrent with prior LOGO's/unreg_rpi's
completing created a race condition where driver rpi ref count can
inadvertantly hit 0 and the rpi attempted to be freed. This error
sometimes resulted in Warning messages indicating kref.h via
lfpc_nlp_get+0x128.

Correct by dropping any new PLOGI until the prior nport state has settled.

Signed-off-by: default avatarDick Kennedy <dick.kennedy@avagotech.com>
Signed-off-by: default avatarJames Smart <james.smart@avagotech.com>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarJames Bottomley <JBottomley@Odin.com>
parent ae374a30
Loading
Loading
Loading
Loading
+3 −11
Original line number Diff line number Diff line
@@ -3668,16 +3668,6 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
	 * At this point, the driver is done so release the IOCB
	 */
	lpfc_els_free_iocb(phba, cmdiocb);

	/*
	 * Remove the ndlp reference if it's a fabric node that has
	 * sent us an unsolicted LOGO.
	 */
	/* FIXME: this one frees ndlp before breaking rport link */
	if (ndlp->nlp_type & NLP_FABRIC)
		lpfc_nlp_put(ndlp);

	return;
}

/**
@@ -4022,6 +4012,8 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
			 ndlp->nlp_rpi, vport->fc_flag);
	if (ndlp->nlp_flag & NLP_LOGO_ACC) {
		spin_lock_irq(shost->host_lock);
		if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED ||
			ndlp->nlp_flag & NLP_REG_LOGIN_SEND))
			ndlp->nlp_flag &= ~NLP_LOGO_ACC;
		spin_unlock_irq(shost->host_lock);
		elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc;
+11 −2
Original line number Diff line number Diff line
@@ -4495,7 +4495,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
{
	struct lpfc_hba *phba = vport->phba;
	LPFC_MBOXQ_t    *mbox;
	int rc;
	int rc, acc_plogi = 1;
	uint16_t rpi;

	if (ndlp->nlp_flag & NLP_RPI_REGISTERED ||
@@ -4528,14 +4528,20 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
					mbox->context1 = lpfc_nlp_get(ndlp);
					mbox->mbox_cmpl =
						lpfc_sli4_unreg_rpi_cmpl_clr;
					/*
					 * accept PLOGIs after unreg_rpi_cmpl
					 */
					acc_plogi = 0;
				} else
					mbox->mbox_cmpl =
						lpfc_sli_def_mbox_cmpl;
			}

			rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
			if (rc == MBX_NOT_FINISHED)
			if (rc == MBX_NOT_FINISHED) {
				mempool_free(mbox, phba->mbox_mem_pool);
				acc_plogi = 1;
			}
		}
		lpfc_no_rpi(phba, ndlp);

@@ -4543,8 +4549,11 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
			ndlp->nlp_rpi = 0;
		ndlp->nlp_flag &= ~NLP_RPI_REGISTERED;
		ndlp->nlp_flag &= ~NLP_NPR_ADISC;
		if (acc_plogi)
			ndlp->nlp_flag &= ~NLP_LOGO_ACC;
		return 1;
	}
	ndlp->nlp_flag &= ~NLP_LOGO_ACC;
	return 0;
}

+1 −1
Original line number Diff line number Diff line
@@ -1874,7 +1874,7 @@ lpfc_rcv_logo_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
	struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg;

	spin_lock_irq(shost->host_lock);
	ndlp->nlp_flag &= NLP_LOGO_ACC;
	ndlp->nlp_flag |= NLP_LOGO_ACC;
	spin_unlock_irq(shost->host_lock);
	lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
	return ndlp->nlp_state;
+1 −1
Original line number Diff line number Diff line
@@ -2249,7 +2249,7 @@ lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
						 vport->vpi, ndlp->nlp_rpi,
						 ndlp->nlp_DID,
						 ndlp->nlp_usg_map, ndlp);
				ndlp->nlp_flag &= ~NLP_LOGO_ACC;
				lpfc_nlp_put(ndlp);
			}
		}