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

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

[SCSI] lpfc 8.1.12 : Reorganize lpfc_nlp_list() and callers to prepare for nodelist simplification



Reorganize lpfc_nlp_list() and callers to prepare for nodelist simplification.

Signed-off-by: default avatarJames Smart <James.Smart@emulex.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 2534ba75
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -43,7 +43,9 @@ void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_nlp_list(struct lpfc_hba *, struct lpfc_nodelist *, int);
void lpfc_dequeue_node(struct lpfc_hba *, struct lpfc_nodelist *);
void lpfc_nlp_set_state(struct lpfc_hba *, struct lpfc_nodelist *, int);
void lpfc_drop_node(struct lpfc_hba *, struct lpfc_nodelist *);
void lpfc_set_disctmo(struct lpfc_hba *);
int lpfc_can_disctmo(struct lpfc_hba *);
int lpfc_unreg_rpi(struct lpfc_hba *, struct lpfc_nodelist *);
+0 −2
Original line number Diff line number Diff line
@@ -83,7 +83,6 @@ struct lpfc_nodelist {
};

/* Defines for nlp_flag (uint32) */
#define NLP_NO_LIST        0x0		/* Indicates immediately free node */
#define NLP_UNUSED_LIST    0x1		/* Flg to indicate node will be freed */
#define NLP_PLOGI_LIST     0x2		/* Flg to indicate sent PLOGI */
#define NLP_ADISC_LIST     0x3		/* Flg to indicate sent ADISC */
@@ -92,7 +91,6 @@ struct lpfc_nodelist {
#define NLP_UNMAPPED_LIST  0x6		/* Node is now unmapped */
#define NLP_MAPPED_LIST    0x7		/* Node is now mapped */
#define NLP_NPR_LIST       0x8		/* Node is in NPort Recovery state */
#define NLP_JUST_DQ        0x9		/* just deque ndlp in lpfc_nlp_list */
#define NLP_LIST_MASK      0xf		/* mask to see what list node is on */
#define NLP_PLOGI_SND      0x20		/* sent PLOGI request for this entry */
#define NLP_PRLI_SND       0x40		/* sent PRLI request for this entry */
+46 −70
Original line number Diff line number Diff line
@@ -387,8 +387,7 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
				sizeof(struct lpfc_name));
		memcpy(&ndlp->nlp_nodename, &sp->nodeName,
				sizeof(struct lpfc_name));
		ndlp->nlp_state = NLP_STE_NPR_NODE;
		lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
		lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
		ndlp->nlp_flag |= NLP_NPR_2B_DISC;
	} else {
		/* This side will wait for the PLOGI */
@@ -605,7 +604,7 @@ lpfc_initial_flogi(struct lpfc_hba * phba)
			return 0;
		lpfc_nlp_init(phba, ndlp, Fabric_DID);
	} else {
		lpfc_nlp_list(phba, ndlp, NLP_JUST_DQ);
		lpfc_dequeue_node(phba, ndlp);
	}
	if (lpfc_issue_els_flogi(phba, ndlp, 0)) {
		mempool_free( ndlp, phba->nlp_mem_pool);
@@ -679,18 +678,15 @@ lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_dmabuf *prsp,
	lpfc_unreg_rpi(phba, new_ndlp);
	new_ndlp->nlp_DID = ndlp->nlp_DID;
	new_ndlp->nlp_prev_state = ndlp->nlp_prev_state;
	new_ndlp->nlp_state = ndlp->nlp_state;
	lpfc_nlp_list(phba, new_ndlp, ndlp->nlp_flag & NLP_LIST_MASK);
	lpfc_nlp_set_state(phba, new_ndlp, ndlp->nlp_state);

	/* Move this back to NPR list */
	if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0) {
		lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
	}
	if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0)
		lpfc_drop_node(phba, ndlp);
	else {
		lpfc_unreg_rpi(phba, ndlp);
		ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */
		ndlp->nlp_state = NLP_STE_NPR_NODE;
		lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
		lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
	}
	return new_ndlp;
}
@@ -704,7 +700,6 @@ lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
	struct lpfc_dmabuf *prsp;
	int disc, rc, did, type;


	/* we pass cmdiocb to state machine which needs rspiocb as well */
	cmdiocb->context_un.rsp_iocb = rspiocb;

@@ -1538,29 +1533,25 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp)
	case ELS_CMD_PLOGI:
		if(!lpfc_issue_els_plogi(phba, ndlp->nlp_DID, retry)) {
			ndlp->nlp_prev_state = ndlp->nlp_state;
			ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
			lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
			lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
		}
		break;
	case ELS_CMD_ADISC:
		if (!lpfc_issue_els_adisc(phba, ndlp, retry)) {
			ndlp->nlp_prev_state = ndlp->nlp_state;
			ndlp->nlp_state = NLP_STE_ADISC_ISSUE;
			lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST);
			lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
		}
		break;
	case ELS_CMD_PRLI:
		if (!lpfc_issue_els_prli(phba, ndlp, retry)) {
			ndlp->nlp_prev_state = ndlp->nlp_state;
			ndlp->nlp_state = NLP_STE_PRLI_ISSUE;
			lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST);
			lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE);
		}
		break;
	case ELS_CMD_LOGO:
		if (!lpfc_issue_els_logo(phba, ndlp, retry)) {
			ndlp->nlp_prev_state = ndlp->nlp_state;
			ndlp->nlp_state = NLP_STE_NPR_NODE;
			lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
			lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
		}
		break;
	}
@@ -1730,8 +1721,7 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
			ndlp->nlp_flag |= NLP_DELAY_TMO;

			ndlp->nlp_prev_state = ndlp->nlp_state;
			ndlp->nlp_state = NLP_STE_NPR_NODE;
			lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
			lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
			ndlp->nlp_last_elscmd = cmd;

			return 1;
@@ -1743,27 +1733,24 @@ lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
		case ELS_CMD_PLOGI:
			if (ndlp) {
				ndlp->nlp_prev_state = ndlp->nlp_state;
				ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
				lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
				lpfc_nlp_set_state(phba, ndlp,
						   NLP_STE_PLOGI_ISSUE);
			}
			lpfc_issue_els_plogi(phba, did, cmdiocb->retry);
			return 1;
		case ELS_CMD_ADISC:
			ndlp->nlp_prev_state = ndlp->nlp_state;
			ndlp->nlp_state = NLP_STE_ADISC_ISSUE;
			lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST);
			lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
			lpfc_issue_els_adisc(phba, ndlp, cmdiocb->retry);
			return 1;
		case ELS_CMD_PRLI:
			ndlp->nlp_prev_state = ndlp->nlp_state;
			ndlp->nlp_state = NLP_STE_PRLI_ISSUE;
			lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST);
			lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE);
			lpfc_issue_els_prli(phba, ndlp, cmdiocb->retry);
			return 1;
		case ELS_CMD_LOGO:
			ndlp->nlp_prev_state = ndlp->nlp_state;
			ndlp->nlp_state = NLP_STE_NPR_NODE;
			lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
			lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
			lpfc_issue_els_logo(phba, ndlp, cmdiocb->retry);
			return 1;
		}
@@ -1827,7 +1814,7 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,

	switch (ndlp->nlp_state) {
	case NLP_STE_UNUSED_NODE:	/* node is just allocated */
		lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
		lpfc_drop_node(phba, ndlp);
		break;
	case NLP_STE_NPR_NODE:		/* NPort Recovery mode */
		lpfc_unreg_rpi(phba, ndlp);
@@ -1885,8 +1872,7 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
			mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
			mbox->context2 = ndlp;
			ndlp->nlp_prev_state = ndlp->nlp_state;
			ndlp->nlp_state = NLP_STE_REG_LOGIN_ISSUE;
			lpfc_nlp_list(phba, ndlp, NLP_REGLOGIN_LIST);
			lpfc_nlp_set_state(phba, ndlp, NLP_STE_REG_LOGIN_ISSUE);
			if (lpfc_sli_issue_mbox(phba, mbox,
						(MBX_NOWAIT | MBX_STOP_IOCB))
			    != MBX_NOT_FINISHED) {
@@ -1901,7 +1887,7 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
			       (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
			       (irsp->un.ulpWord[4] == IOERR_SLI_DOWN)))) {
				if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
					lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
					lpfc_drop_node(phba, ndlp);
					ndlp = NULL;
				}
			}
@@ -2311,9 +2297,8 @@ lpfc_els_disc_adisc(struct lpfc_hba * phba)
			if (ndlp->nlp_flag & NLP_NPR_ADISC) {
				ndlp->nlp_flag &= ~NLP_NPR_ADISC;
				ndlp->nlp_prev_state = ndlp->nlp_state;
				ndlp->nlp_state = NLP_STE_ADISC_ISSUE;
				lpfc_nlp_list(phba, ndlp,
					NLP_ADISC_LIST);
				lpfc_nlp_set_state(phba, ndlp,
						   NLP_STE_ADISC_ISSUE);
				lpfc_issue_els_adisc(phba, ndlp, 0);
				sentadisc++;
				phba->num_disc_nodes++;
@@ -2349,8 +2334,8 @@ lpfc_els_disc_plogi(struct lpfc_hba * phba)
		   (!(ndlp->nlp_flag & NLP_DELAY_TMO))) {
			if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
				ndlp->nlp_prev_state = ndlp->nlp_state;
				ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
				lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
				lpfc_nlp_set_state(phba, ndlp,
						   NLP_STE_PLOGI_ISSUE);
				lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
				sentplogi++;
				phba->num_disc_nodes++;
@@ -2647,8 +2632,7 @@ lpfc_els_handle_rscn(struct lpfc_hba * phba)
			lpfc_nlp_init(phba, ndlp, NameServer_DID);
			ndlp->nlp_type |= NLP_FABRIC;
			ndlp->nlp_prev_state = ndlp->nlp_state;
			ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
			lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
			lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
			lpfc_issue_els_plogi(phba, NameServer_DID, 0);
			/* Wait for NameServer login cmpl before we can
			   continue */
@@ -3074,8 +3058,8 @@ lpfc_els_rcv_farp(struct lpfc_hba * phba,
			/* Log back into the node before sending the FARP. */
			if (fp->Rflags & FARP_REQUEST_PLOGI) {
				ndlp->nlp_prev_state = ndlp->nlp_state;
				ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
				lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
				lpfc_nlp_set_state(phba, ndlp,
						   NLP_STE_PLOGI_ISSUE);
				lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
			}

@@ -3159,7 +3143,7 @@ lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
					 * Clean up old Fabric, Nameserver and
					 * other NLP_FABRIC logins
					 */
					lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
					lpfc_drop_node(phba, ndlp);
				} else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
					/* Fail outstanding I/O now since this
					 * device is marked for PLOGI
@@ -3182,14 +3166,14 @@ lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
			switch (ndlp->nlp_prev_state) {
			case NLP_STE_UNMAPPED_NODE:
				ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
				ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
				lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
				lpfc_nlp_set_state(phba, ndlp,
						   NLP_STE_UNMAPPED_NODE);
				break;

			case NLP_STE_MAPPED_NODE:
				ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
				ndlp->nlp_state = NLP_STE_MAPPED_NODE;
				lpfc_nlp_list(phba, ndlp, NLP_MAPPED_LIST);
				lpfc_nlp_set_state(phba, ndlp,
						   NLP_STE_MAPPED_NODE);
				break;

			default:
@@ -3431,8 +3415,7 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
		if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) {
			ndlp->nlp_type |= NLP_FABRIC;
		}
		ndlp->nlp_state = NLP_STE_UNUSED_NODE;
		lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);
		lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
	}

	phba->fc_stat.elsRcvFrame++;
@@ -3460,9 +3443,8 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
	case ELS_CMD_FLOGI:
		phba->fc_stat.elsRcvFLOGI++;
		lpfc_els_rcv_flogi(phba, elsiocb, ndlp, newnode);
		if (newnode) {
			lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
		}
		if (newnode)
			lpfc_drop_node(phba, ndlp);
		break;
	case ELS_CMD_LOGO:
		phba->fc_stat.elsRcvLOGO++;
@@ -3483,9 +3465,8 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
	case ELS_CMD_RSCN:
		phba->fc_stat.elsRcvRSCN++;
		lpfc_els_rcv_rscn(phba, elsiocb, ndlp, newnode);
		if (newnode) {
			lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
		}
		if (newnode)
			lpfc_drop_node(phba, ndlp);
		break;
	case ELS_CMD_ADISC:
		phba->fc_stat.elsRcvADISC++;
@@ -3526,30 +3507,26 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
	case ELS_CMD_LIRR:
		phba->fc_stat.elsRcvLIRR++;
		lpfc_els_rcv_lirr(phba, elsiocb, ndlp);
		if (newnode) {
			lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
		}
		if (newnode)
			lpfc_drop_node(phba, ndlp);
		break;
	case ELS_CMD_RPS:
		phba->fc_stat.elsRcvRPS++;
		lpfc_els_rcv_rps(phba, elsiocb, ndlp);
		if (newnode) {
			lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
		}
		if (newnode)
			lpfc_drop_node(phba, ndlp);
		break;
	case ELS_CMD_RPL:
		phba->fc_stat.elsRcvRPL++;
		lpfc_els_rcv_rpl(phba, elsiocb, ndlp);
		if (newnode) {
			lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
		}
		if (newnode)
			lpfc_drop_node(phba, ndlp);
		break;
	case ELS_CMD_RNID:
		phba->fc_stat.elsRcvRNID++;
		lpfc_els_rcv_rnid(phba, elsiocb, ndlp);
		if (newnode) {
			lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
		}
		if (newnode)
			lpfc_drop_node(phba, ndlp);
		break;
	default:
		/* Unsupported ELS command, reject */
@@ -3559,9 +3536,8 @@ lpfc_els_unsol_event(struct lpfc_hba * phba,
		lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
				"%d:0115 Unknown ELS command x%x received from "
				"NPORT x%x\n", phba->brd_no, cmd, did);
		if (newnode) {
			lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
		}
		if (newnode)
			lpfc_drop_node(phba, ndlp);
		break;
	}

+169 −128
Original line number Diff line number Diff line
@@ -429,9 +429,8 @@ lpfc_linkdown(struct lpfc_hba * phba)

	/* free any ndlp's on unused list */
	list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list,
				nlp_listp) {
		lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
	}
				nlp_listp)
		lpfc_drop_node(phba, ndlp);

	/* Setup myDID for link up if we are in pt2pt mode */
	if (phba->fc_flag & FC_PT2PT) {
@@ -497,8 +496,8 @@ lpfc_linkup(struct lpfc_hba * phba)
					/* On Linkup its safe to clean up the
					 * ndlp from Fabric connections.
					 */
					lpfc_nlp_list(phba, ndlp,
							NLP_UNUSED_LIST);
					lpfc_nlp_set_state(phba, ndlp,
						       NLP_STE_UNUSED_NODE);
				} else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
					/* Fail outstanding IO now since device
					 * is marked for PLOGI.
@@ -511,9 +510,8 @@ lpfc_linkup(struct lpfc_hba * phba)

	/* free any ndlp's on unused list */
	list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list,
				nlp_listp) {
		lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
	}
				nlp_listp)
		lpfc_drop_node(phba, ndlp);

	return 0;
}
@@ -993,8 +991,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)

	ndlp->nlp_rpi = mb->un.varWords[0];
	ndlp->nlp_type |= NLP_FABRIC;
	ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
	lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
	lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);

	if (phba->hba_state == LPFC_FABRIC_CFG_LINK) {
		/* This NPort has been assigned an NPort_ID by the fabric as a
@@ -1024,8 +1021,7 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
				ndlp->nlp_type |= NLP_FABRIC;
			}
		}
		ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
		lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
		lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
		lpfc_issue_els_plogi(phba, NameServer_DID, 0);
		if (phba->cfg_fdmi_on) {
			ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool,
@@ -1069,7 +1065,7 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
		lpfc_mbuf_free(phba, mp->virt, mp->phys);
		kfree(mp);
		mempool_free(pmb, phba->mbox_mem_pool);
		lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
		lpfc_drop_node(phba, ndlp);

		/* RegLogin failed, so just use loop map to make discovery
		   list */
@@ -1084,8 +1080,7 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)

	ndlp->nlp_rpi = mb->un.varWords[0];
	ndlp->nlp_type |= NLP_FABRIC;
	ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
	lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
	lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);

	if (phba->hba_state < LPFC_HBA_READY) {
		/* Link up discovery requires Fabrib registration. */
@@ -1170,72 +1165,82 @@ lpfc_unregister_remote_port(struct lpfc_hba * phba,
	return;
}

int
lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
static void
lpfc_nlp_counters(struct lpfc_hba *phba, int state, int count)
{
	enum { none, unmapped, mapped } rport_add = none, rport_del = none;
	struct lpfc_sli      *psli;

	psli = &phba->sli;
	/* Sanity check to ensure we are not moving to / from the same list */
	if ((nlp->nlp_flag & NLP_LIST_MASK) == list)
		if (list != NLP_NO_LIST)
			return 0;

	spin_lock_irq(phba->host->host_lock);
	switch (nlp->nlp_flag & NLP_LIST_MASK) {
	case NLP_NO_LIST: /* Not on any list */
	switch (state) {
	case NLP_STE_UNUSED_NODE:
		phba->fc_unused_cnt += count;
		break;
	case NLP_STE_PLOGI_ISSUE:
		phba->fc_plogi_cnt += count;
		break;
	case NLP_STE_ADISC_ISSUE:
		phba->fc_adisc_cnt += count;
		break;
	case NLP_STE_REG_LOGIN_ISSUE:
		phba->fc_reglogin_cnt += count;
		break;
	case NLP_STE_PRLI_ISSUE:
		phba->fc_prli_cnt += count;
		break;
	case NLP_STE_UNMAPPED_NODE:
		phba->fc_unmap_cnt += count;
		break;
	case NLP_STE_MAPPED_NODE:
		phba->fc_map_cnt += count;
		break;
	case NLP_STE_NPR_NODE:
		phba->fc_npr_cnt += count;
		break;
	}
}

void
lpfc_delink_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
{
	switch (ndlp->nlp_flag & NLP_LIST_MASK) {
	case NLP_UNUSED_LIST:
		phba->fc_unused_cnt--;
		list_del(&nlp->nlp_listp);
		list_del_init(&ndlp->nlp_listp);
		break;
	case NLP_PLOGI_LIST:
		phba->fc_plogi_cnt--;
		list_del(&nlp->nlp_listp);
		list_del_init(&ndlp->nlp_listp);
		break;
	case NLP_ADISC_LIST:
		phba->fc_adisc_cnt--;
		list_del(&nlp->nlp_listp);
		list_del_init(&ndlp->nlp_listp);
		break;
	case NLP_REGLOGIN_LIST:
		phba->fc_reglogin_cnt--;
		list_del(&nlp->nlp_listp);
		list_del_init(&ndlp->nlp_listp);
		break;
	case NLP_PRLI_LIST:
		phba->fc_prli_cnt--;
		list_del(&nlp->nlp_listp);
		list_del_init(&ndlp->nlp_listp);
		break;
	case NLP_UNMAPPED_LIST:
		phba->fc_unmap_cnt--;
		list_del(&nlp->nlp_listp);
		nlp->nlp_flag &= ~NLP_TGT_NO_SCSIID;
		nlp->nlp_type &= ~NLP_FC_NODE;
		phba->nport_event_cnt++;
		if (nlp->rport)
			rport_del = unmapped;
		list_del_init(&ndlp->nlp_listp);
		break;
	case NLP_MAPPED_LIST:
		phba->fc_map_cnt--;
		list_del(&nlp->nlp_listp);
		phba->nport_event_cnt++;
		if (nlp->rport)
			rport_del = mapped;
		list_del_init(&ndlp->nlp_listp);
		break;
	case NLP_NPR_LIST:
		phba->fc_npr_cnt--;
		list_del(&nlp->nlp_listp);
		/* Stop delay tmo if taking node off NPR list */
		if ((nlp->nlp_flag & NLP_DELAY_TMO) &&
		   (list != NLP_NPR_LIST)) {
			spin_unlock_irq(phba->host->host_lock);
			lpfc_cancel_retry_delay_tmo(phba, nlp);
			spin_lock_irq(phba->host->host_lock);
		}
		list_del_init(&ndlp->nlp_listp);
		break;
	}

	nlp->nlp_flag &= ~NLP_LIST_MASK;
	ndlp->nlp_flag &= ~NLP_LIST_MASK;
}

static int
lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
{
	struct lpfc_sli      *psli;

	psli = &phba->sli;
	/* Sanity check to ensure we are not moving to / from the same list */
	if ((nlp->nlp_flag & NLP_LIST_MASK) == list)
		return 0;

	spin_lock_irq(phba->host->host_lock);
	lpfc_delink_node(phba, nlp);

	/* Add NPort <did> to <num> list */
	lpfc_printf_log(phba,
@@ -1246,102 +1251,85 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
			nlp->nlp_DID, list, nlp->nlp_flag);

	switch (list) {
	case NLP_NO_LIST: /* No list, just remove it */
		spin_unlock_irq(phba->host->host_lock);
		lpfc_nlp_remove(phba, nlp);
		spin_lock_irq(phba->host->host_lock);
		/* as node removed - stop further transport calls */
		rport_del = none;
		break;
	case NLP_UNUSED_LIST:
		nlp->nlp_flag |= list;
		/* Put it at the end of the unused list */
		list_add_tail(&nlp->nlp_listp, &phba->fc_unused_list);
		phba->fc_unused_cnt++;
		break;
	case NLP_PLOGI_LIST:
		nlp->nlp_flag |= list;
		/* Put it at the end of the plogi list */
		list_add_tail(&nlp->nlp_listp, &phba->fc_plogi_list);
		phba->fc_plogi_cnt++;
		break;
	case NLP_ADISC_LIST:
		nlp->nlp_flag |= list;
		/* Put it at the end of the adisc list */
		list_add_tail(&nlp->nlp_listp, &phba->fc_adisc_list);
		phba->fc_adisc_cnt++;
		break;
	case NLP_REGLOGIN_LIST:
		nlp->nlp_flag |= list;
		/* Put it at the end of the reglogin list */
		list_add_tail(&nlp->nlp_listp, &phba->fc_reglogin_list);
		phba->fc_reglogin_cnt++;
		break;
	case NLP_PRLI_LIST:
		nlp->nlp_flag |= list;
		/* Put it at the end of the prli list */
		list_add_tail(&nlp->nlp_listp, &phba->fc_prli_list);
		phba->fc_prli_cnt++;
		break;
	case NLP_UNMAPPED_LIST:
		rport_add = unmapped;
		/* ensure all vestiges of "mapped" significance are gone */
		nlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
		nlp->nlp_flag |= list;
		/* Put it at the end of the unmap list */
		list_add_tail(&nlp->nlp_listp, &phba->fc_nlpunmap_list);
		phba->fc_unmap_cnt++;
		phba->nport_event_cnt++;
		nlp->nlp_flag &= ~NLP_NODEV_REMOVE;
		nlp->nlp_type |= NLP_FC_NODE;
		break;
	case NLP_MAPPED_LIST:
		rport_add = mapped;
		nlp->nlp_flag |= list;
		/* Put it at the end of the map list */
		list_add_tail(&nlp->nlp_listp, &phba->fc_nlpmap_list);
		phba->fc_map_cnt++;
		phba->nport_event_cnt++;
		nlp->nlp_flag &= ~NLP_NODEV_REMOVE;
		break;
	case NLP_NPR_LIST:
		nlp->nlp_flag |= list;
		/* Put it at the end of the npr list */
		list_add_tail(&nlp->nlp_listp, &phba->fc_npr_list);
		phba->fc_npr_cnt++;

		nlp->nlp_flag &= ~NLP_RCV_PLOGI;
		break;
	case NLP_JUST_DQ:
		break;
	}

	spin_unlock_irq(phba->host->host_lock);
	return 0;
}

	/*
	 * We make all the calls into the transport after we have
	 * moved the node between lists. This so that we don't
	 * release the lock while in-between lists.
	 */

	/* Don't upcall midlayer if we're unloading */
	if (!(phba->fc_flag & FC_UNLOADING)) {
		/*
		 * We revalidate the rport pointer as the "add" function
		 * may have removed the remote port.
		 */
		if ((rport_del != none) && nlp->rport)
			lpfc_unregister_remote_port(phba, nlp);
static void
lpfc_nlp_state_cleanup(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
		       int old_state, int new_state)
{
	if (new_state == NLP_STE_UNMAPPED_NODE) {
		ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
		ndlp->nlp_flag &= ~NLP_NODEV_REMOVE;
		ndlp->nlp_type |= NLP_FC_NODE;
	}
	if (new_state == NLP_STE_MAPPED_NODE)
		ndlp->nlp_flag &= ~NLP_NODEV_REMOVE;
	if (new_state == NLP_STE_NPR_NODE)
		ndlp->nlp_flag &= ~NLP_RCV_PLOGI;

	/* Transport interface */
	if (ndlp->rport && (old_state == NLP_STE_MAPPED_NODE ||
			    old_state == NLP_STE_UNMAPPED_NODE)) {
		phba->nport_event_cnt++;
		lpfc_unregister_remote_port(phba, ndlp);
	}

		if (rport_add != none) {
	if (new_state ==  NLP_STE_MAPPED_NODE ||
	    new_state == NLP_STE_UNMAPPED_NODE) {
		phba->nport_event_cnt++;
			/*
			 * Tell the fc transport about the port, if we haven't
			 * already. If we have, and it's a scsi entity, be
			 * sure to unblock any attached scsi devices
			 */
			if ((!nlp->rport) || (nlp->rport->port_state ==
					FC_PORTSTATE_BLOCKED))
				lpfc_register_remote_port(phba, nlp);
		if (!ndlp->rport ||
		    ndlp->rport->port_state == FC_PORTSTATE_BLOCKED)
			lpfc_register_remote_port(phba, ndlp);
	}

			/*
			 * if we added to Mapped list, but the remote port
@@ -1349,19 +1337,75 @@ lpfc_nlp_list(struct lpfc_hba * phba, struct lpfc_nodelist * nlp, int list)
			 * our presentable range - move the node to the
			 * Unmapped List
			 */
			if ((rport_add == mapped) &&
			    ((!nlp->rport) ||
			     (nlp->rport->scsi_target_id == -1) ||
			     (nlp->rport->scsi_target_id >= LPFC_MAX_TARGET))) {
				nlp->nlp_state = NLP_STE_UNMAPPED_NODE;
	if (new_state == NLP_STE_MAPPED_NODE &&
	    (!ndlp->rport ||
	     ndlp->rport->scsi_target_id == -1 ||
	     ndlp->rport->scsi_target_id >= LPFC_MAX_TARGET)) {
		spin_lock_irq(phba->host->host_lock);
				nlp->nlp_flag |= NLP_TGT_NO_SCSIID;
		ndlp->nlp_flag |= NLP_TGT_NO_SCSIID;
		spin_unlock_irq(phba->host->host_lock);
				lpfc_nlp_list(phba, nlp, NLP_UNMAPPED_LIST);
		lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
	}
}

void
lpfc_nlp_set_state(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp, int state)
{
	int  old_state = ndlp->nlp_state;
	static int  list_id[] = {
		[NLP_STE_UNUSED_NODE] = NLP_UNUSED_LIST,
		[NLP_STE_PLOGI_ISSUE] = NLP_PLOGI_LIST,
		[NLP_STE_ADISC_ISSUE] = NLP_ADISC_LIST,
		[NLP_STE_REG_LOGIN_ISSUE] = NLP_REGLOGIN_LIST,
		[NLP_STE_PRLI_ISSUE] = NLP_PRLI_LIST,
		[NLP_STE_UNMAPPED_NODE] = NLP_UNMAPPED_LIST,
		[NLP_STE_MAPPED_NODE] = NLP_MAPPED_LIST,
		[NLP_STE_NPR_NODE] = NLP_NPR_LIST,
	};

	if (old_state == NLP_STE_NPR_NODE &&
	    (ndlp->nlp_flag & NLP_DELAY_TMO) != 0 &&
	    state != NLP_STE_NPR_NODE)
		lpfc_cancel_retry_delay_tmo(phba, ndlp);
	if (old_state == NLP_STE_UNMAPPED_NODE) {
		ndlp->nlp_flag &= ~NLP_TGT_NO_SCSIID;
		ndlp->nlp_type &= ~NLP_FC_NODE;
	}
	return 0;

	if (old_state && !list_empty(&ndlp->nlp_listp))
		lpfc_nlp_counters(phba, old_state, -1);

	ndlp->nlp_state = state;
	lpfc_nlp_list(phba, ndlp, list_id[state]);
	lpfc_nlp_counters(phba, state, 1);

	lpfc_nlp_state_cleanup(phba, ndlp, old_state, state);
}

void
lpfc_dequeue_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
{
	if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0)
		lpfc_cancel_retry_delay_tmo(phba, ndlp);
	spin_lock_irq(phba->host->host_lock);
	if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp))
		lpfc_nlp_counters(phba, ndlp->nlp_state, -1);
	lpfc_delink_node(phba, ndlp);
	spin_unlock_irq(phba->host->host_lock);
	lpfc_nlp_state_cleanup(phba, ndlp, ndlp->nlp_state, 0);
}

void
lpfc_drop_node(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
{
	if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0)
		lpfc_cancel_retry_delay_tmo(phba, ndlp);
	spin_lock_irq(phba->host->host_lock);
	if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp))
		lpfc_nlp_counters(phba, ndlp->nlp_state, -1);
	lpfc_delink_node(phba, ndlp);
	spin_unlock_irq(phba->host->host_lock);
	lpfc_nlp_remove(phba, ndlp);
}

/*
@@ -1577,7 +1621,7 @@ lpfc_freenode(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
			phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
			ndlp->nlp_state, ndlp->nlp_rpi);

	lpfc_nlp_list(phba, ndlp, NLP_JUST_DQ);
	lpfc_dequeue_node(phba, ndlp);

	/* cleanup any ndlp on mbox q waiting for reglogin cmpl */
	if ((mb = phba->sli.mbox_active)) {
@@ -1771,8 +1815,7 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did)
		if (!ndlp)
			return NULL;
		lpfc_nlp_init(phba, ndlp, did);
		ndlp->nlp_state = NLP_STE_NPR_NODE;
		lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
		lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
		ndlp->nlp_flag |= NLP_NPR_2B_DISC;
		return ndlp;
	}
@@ -1791,8 +1834,7 @@ lpfc_setup_disc_node(struct lpfc_hba * phba, uint32_t did)
		flg = ndlp->nlp_flag & NLP_LIST_MASK;
		if ((flg == NLP_ADISC_LIST) || (flg == NLP_PLOGI_LIST))
			return NULL;
		ndlp->nlp_state = NLP_STE_NPR_NODE;
		lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
		lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
		ndlp->nlp_flag |= NLP_NPR_2B_DISC;
	}
	return ndlp;
@@ -2099,7 +2141,7 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
					nlp_listp) {
			if (ndlp->nlp_type & NLP_FABRIC) {
				/* Clean up the ndlp on Fabric connections */
				lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
				lpfc_drop_node(phba, ndlp);
			} else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
				/* Fail outstanding IO now since device
				 * is marked for PLOGI.
@@ -2304,8 +2346,7 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)

	ndlp->nlp_rpi = mb->un.varWords[0];
	ndlp->nlp_type |= NLP_FABRIC;
	ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
	lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
	lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);

	/* Start issuing Fabric-Device Management Interface (FDMI)
	 * command to 0xfffffa (FDMI well known port)
+1 −1
Original line number Diff line number Diff line
@@ -1196,7 +1196,7 @@ lpfc_cleanup(struct lpfc_hba * phba)

	list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list,
				nlp_listp) {
		lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
		lpfc_drop_node(phba, ndlp);
	}

	list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list,
Loading