Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fe83e3b

Browse files
jsmart-ghmartinkpetersen
authored andcommitted
scsi: lpfc: Fix node handling for Fabric Controller and Domain Controller
During link bounce testing, RPI counts were seen to differ from the number of nodes. For fabric and domain controllers, a temporary RPI is assigned, but the code isn't registering it. If the nodes do go away, such as on link down, the temporary RPI isn't being released. Change the way these two fabric services are managed, make them behave like any other remote port. Register the RPI and register with the transport. Never leave the nodes in a NPR or UNUSED state where their RPI is in limbo. This allows them to follow normal dev_loss_tmo handling, RPI refcounting, and normal removal rules. It also allows fabric I/Os to use the RPI for traffic requests. Note: There is some logic that still has a couple of exceptions when the Domain controller (0xfffcXX). There are cases where the fabric won't have a valid login but will send RDP. Other times, it will it send a LOGO then an RDP. It makes for ad-hoc behavior to manage the node. Exceptions are documented in the code. Link: https://lore.kernel.org/r/[email protected] Co-developed-by: Justin Tee <[email protected]> Signed-off-by: Justin Tee <[email protected]> Signed-off-by: James Smart <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 4012bae commit fe83e3b

File tree

7 files changed

+189
-20
lines changed

7 files changed

+189
-20
lines changed

drivers/scsi/lpfc/lpfc_crtn.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
8080
void lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *, LPFC_MBOXQ_t *);
8181
void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
8282
void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
83+
void lpfc_mbx_cmpl_fc_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb);
8384
void lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
8485
void lpfc_mbx_cmpl_reg_vfi(struct lpfc_hba *, LPFC_MBOXQ_t *);
8586
void lpfc_unregister_vfi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);

drivers/scsi/lpfc/lpfc_debugfs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -863,10 +863,10 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
863863
len += scnprintf(buf+len, size-len, "%s DID:x%06x ",
864864
statep, ndlp->nlp_DID);
865865
len += scnprintf(buf+len, size-len,
866-
"WWPN x%llx ",
866+
"WWPN x%016llx ",
867867
wwn_to_u64(ndlp->nlp_portname.u.wwn));
868868
len += scnprintf(buf+len, size-len,
869-
"WWNN x%llx ",
869+
"WWNN x%016llx ",
870870
wwn_to_u64(ndlp->nlp_nodename.u.wwn));
871871
len += scnprintf(buf+len, size-len, "RPI:x%04x ",
872872
ndlp->nlp_rpi);

drivers/scsi/lpfc/lpfc_disc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ enum lpfc_fc4_xpt_flags {
8686

8787
struct lpfc_nodelist {
8888
struct list_head nlp_listp;
89+
struct serv_parm fc_sparam; /* buffer for service params */
8990
struct lpfc_name nlp_portname;
9091
struct lpfc_name nlp_nodename;
9192

drivers/scsi/lpfc/lpfc_els.c

Lines changed: 124 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3085,6 +3085,95 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
30853085
lpfc_nlp_put(free_ndlp);
30863086
}
30873087

3088+
/**
3089+
* lpfc_reg_fab_ctrl_node - RPI register the fabric controller node.
3090+
* @vport: pointer to lpfc_vport data structure.
3091+
* @fc_ndlp: pointer to the fabric controller (0xfffffd) node.
3092+
*
3093+
* This routine registers the rpi assigned to the fabric controller
3094+
* NPort_ID (0xfffffd) with the port and moves the node to UNMAPPED
3095+
* state triggering a registration with the SCSI transport.
3096+
*
3097+
* This routine is single out because the fabric controller node
3098+
* does not receive a PLOGI. This routine is consumed by the
3099+
* SCR and RDF ELS commands. Callers are expected to qualify
3100+
* with SLI4 first.
3101+
**/
3102+
static int
3103+
lpfc_reg_fab_ctrl_node(struct lpfc_vport *vport, struct lpfc_nodelist *fc_ndlp)
3104+
{
3105+
int rc = 0;
3106+
struct lpfc_hba *phba = vport->phba;
3107+
struct lpfc_nodelist *ns_ndlp;
3108+
LPFC_MBOXQ_t *mbox;
3109+
struct lpfc_dmabuf *mp;
3110+
3111+
if (fc_ndlp->nlp_flag & NLP_RPI_REGISTERED)
3112+
return rc;
3113+
3114+
ns_ndlp = lpfc_findnode_did(vport, NameServer_DID);
3115+
if (!ns_ndlp)
3116+
return -ENODEV;
3117+
3118+
lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE,
3119+
"0935 %s: Reg FC RPI x%x on FC DID x%x NSSte: x%x\n",
3120+
__func__, fc_ndlp->nlp_rpi, fc_ndlp->nlp_DID,
3121+
ns_ndlp->nlp_state);
3122+
if (ns_ndlp->nlp_state != NLP_STE_UNMAPPED_NODE)
3123+
return -ENODEV;
3124+
3125+
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
3126+
if (!mbox) {
3127+
lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
3128+
"0936 %s: no memory for reg_login "
3129+
"Data: x%x x%x x%x x%x\n", __func__,
3130+
fc_ndlp->nlp_DID, fc_ndlp->nlp_state,
3131+
fc_ndlp->nlp_flag, fc_ndlp->nlp_rpi);
3132+
return -ENOMEM;
3133+
}
3134+
rc = lpfc_reg_rpi(phba, vport->vpi, fc_ndlp->nlp_DID,
3135+
(u8 *)&vport->fc_sparam, mbox, fc_ndlp->nlp_rpi);
3136+
if (rc) {
3137+
rc = -EACCES;
3138+
goto out;
3139+
}
3140+
3141+
fc_ndlp->nlp_flag |= NLP_REG_LOGIN_SEND;
3142+
mbox->mbox_cmpl = lpfc_mbx_cmpl_fc_reg_login;
3143+
mbox->ctx_ndlp = lpfc_nlp_get(fc_ndlp);
3144+
if (!mbox->ctx_ndlp) {
3145+
rc = -ENOMEM;
3146+
goto out_mem;
3147+
}
3148+
3149+
mbox->vport = vport;
3150+
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
3151+
if (rc == MBX_NOT_FINISHED) {
3152+
rc = -ENODEV;
3153+
lpfc_nlp_put(fc_ndlp);
3154+
goto out_mem;
3155+
}
3156+
/* Success path. Exit. */
3157+
lpfc_nlp_set_state(vport, fc_ndlp,
3158+
NLP_STE_REG_LOGIN_ISSUE);
3159+
return 0;
3160+
3161+
out_mem:
3162+
fc_ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND;
3163+
mp = (struct lpfc_dmabuf *)mbox->ctx_buf;
3164+
lpfc_mbuf_free(phba, mp->virt, mp->phys);
3165+
kfree(mp);
3166+
3167+
out:
3168+
mempool_free(mbox, phba->mbox_mem_pool);
3169+
lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
3170+
"0938 %s: failed to format reg_login "
3171+
"Data: x%x x%x x%x x%x\n", __func__,
3172+
fc_ndlp->nlp_DID, fc_ndlp->nlp_state,
3173+
fc_ndlp->nlp_flag, fc_ndlp->nlp_rpi);
3174+
return rc;
3175+
}
3176+
30883177
/**
30893178
* lpfc_cmpl_els_disc_cmd - Completion callback function for Discovery ELS cmd
30903179
* @phba: pointer to lpfc hba data structure.
@@ -3231,10 +3320,18 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
32313320

32323321
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
32333322
ndlp->nlp_DID, ELS_CMD_SCR);
3234-
32353323
if (!elsiocb)
32363324
return 1;
32373325

3326+
if (phba->sli_rev == LPFC_SLI_REV4) {
3327+
rc = lpfc_reg_fab_ctrl_node(vport, ndlp);
3328+
if (rc) {
3329+
lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
3330+
"0937 %s: Failed to reg fc node, rc %d\n",
3331+
__func__, rc);
3332+
return 1;
3333+
}
3334+
}
32383335
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
32393336

32403337
*((uint32_t *) (pcmd)) = ELS_CMD_SCR;
@@ -3522,6 +3619,17 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
35223619
if (!elsiocb)
35233620
return -ENOMEM;
35243621

3622+
if (phba->sli_rev == LPFC_SLI_REV4 &&
3623+
!(ndlp->nlp_flag & NLP_RPI_REGISTERED)) {
3624+
lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
3625+
"0939 %s: FC_NODE x%x RPI x%x flag x%x "
3626+
"ste x%x type x%x Not registered\n",
3627+
__func__, ndlp->nlp_DID, ndlp->nlp_rpi,
3628+
ndlp->nlp_flag, ndlp->nlp_state,
3629+
ndlp->nlp_type);
3630+
return -ENODEV;
3631+
}
3632+
35253633
/* Configure the payload for the supported FPIN events. */
35263634
prdf = (struct lpfc_els_rdf_req *)
35273635
(((struct lpfc_dmabuf *)elsiocb->context2)->virt);
@@ -4396,7 +4504,6 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
43964504
struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
43974505
struct lpfc_vport *vport = cmdiocb->vport;
43984506
IOCB_t *irsp;
4399-
u32 xpt_flags = 0, did_mask = 0;
44004507

44014508
irsp = &rspiocb->iocb;
44024509
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
@@ -4409,23 +4516,27 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
44094516
ndlp->nlp_DID, kref_read(&ndlp->kref), ndlp->nlp_flag,
44104517
ndlp->nlp_state, ndlp->nlp_rpi);
44114518

4519+
/* This clause allows the LOGO ACC to complete and free resources
4520+
* for the Fabric Domain Controller. It does deliberately skip
4521+
* the unreg_rpi and release rpi because some fabrics send RDP
4522+
* requests after logging out from the initiator.
4523+
*/
4524+
if (ndlp->nlp_type & NLP_FABRIC &&
4525+
((ndlp->nlp_DID & WELL_KNOWN_DID_MASK) != WELL_KNOWN_DID_MASK))
4526+
goto out;
4527+
44124528
if (ndlp->nlp_state == NLP_STE_NPR_NODE) {
44134529
/* NPort Recovery mode or node is just allocated */
44144530
if (!lpfc_nlp_not_used(ndlp)) {
44154531
/* A LOGO is completing and the node is in NPR state.
44164532
* If this a fabric node that cleared its transport
44174533
* registration, release the rpi.
44184534
*/
4419-
xpt_flags = SCSI_XPT_REGD | NVME_XPT_REGD;
4420-
did_mask = ndlp->nlp_DID & Fabric_DID_MASK;
4421-
if (did_mask == Fabric_DID_MASK &&
4422-
!(ndlp->fc4_xpt_flags & xpt_flags)) {
4423-
spin_lock_irq(&ndlp->lock);
4424-
ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
4425-
if (phba->sli_rev == LPFC_SLI_REV4)
4426-
ndlp->nlp_flag |= NLP_RELEASE_RPI;
4427-
spin_unlock_irq(&ndlp->lock);
4428-
}
4535+
spin_lock_irq(&ndlp->lock);
4536+
ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
4537+
if (phba->sli_rev == LPFC_SLI_REV4)
4538+
ndlp->nlp_flag |= NLP_RELEASE_RPI;
4539+
spin_unlock_irq(&ndlp->lock);
44294540
lpfc_unreg_rpi(vport, ndlp);
44304541
} else {
44314542
/* Indicate the node has already released, should
@@ -4434,7 +4545,7 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
44344545
cmdiocb->context1 = NULL;
44354546
}
44364547
}
4437-
4548+
out:
44384549
/*
44394550
* The driver received a LOGO from the rport and has ACK'd it.
44404551
* At this point, the driver is done so release the IOCB

drivers/scsi/lpfc/lpfc_hbadisc.c

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,7 @@ static int
7777
lpfc_valid_xpt_node(struct lpfc_nodelist *ndlp)
7878
{
7979
if (ndlp->nlp_fc4_type ||
80-
ndlp->nlp_DID == Fabric_DID ||
81-
ndlp->nlp_DID == NameServer_DID ||
82-
ndlp->nlp_DID == FDMI_DID)
80+
ndlp->nlp_type & NLP_FABRIC)
8381
return 1;
8482
return 0;
8583
}
@@ -826,7 +824,8 @@ lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove)
826824
if ((phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) ||
827825
((vport->port_type == LPFC_NPIV_PORT) &&
828826
((ndlp->nlp_DID == NameServer_DID) ||
829-
(ndlp->nlp_DID == FDMI_DID))))
827+
(ndlp->nlp_DID == FDMI_DID) ||
828+
(ndlp->nlp_DID == Fabric_Cntl_DID))))
830829
lpfc_unreg_rpi(vport, ndlp);
831830

832831
/* Leave Fabric nodes alone on link down */
@@ -4160,6 +4159,53 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
41604159
return;
41614160
}
41624161

4162+
/*
4163+
* This routine handles processing a Fabric Controller REG_LOGIN mailbox
4164+
* command upon completion. It is setup in the LPFC_MBOXQ
4165+
* as the completion routine when the command is handed off to the SLI layer.
4166+
*/
4167+
void
4168+
lpfc_mbx_cmpl_fc_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
4169+
{
4170+
struct lpfc_vport *vport = pmb->vport;
4171+
MAILBOX_t *mb = &pmb->u.mb;
4172+
struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *)(pmb->ctx_buf);
4173+
struct lpfc_nodelist *ndlp;
4174+
4175+
ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp;
4176+
pmb->ctx_ndlp = NULL;
4177+
pmb->ctx_buf = NULL;
4178+
4179+
if (mb->mbxStatus) {
4180+
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
4181+
"0933 %s: Register FC login error: 0x%x\n",
4182+
__func__, mb->mbxStatus);
4183+
goto out;
4184+
}
4185+
4186+
if (phba->sli_rev < LPFC_SLI_REV4)
4187+
ndlp->nlp_rpi = mb->un.varWords[0];
4188+
4189+
lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE,
4190+
"0934 %s: Complete FC x%x RegLogin rpi x%x ste x%x\n",
4191+
__func__, ndlp->nlp_DID, ndlp->nlp_rpi,
4192+
ndlp->nlp_state);
4193+
4194+
ndlp->nlp_flag |= NLP_RPI_REGISTERED;
4195+
ndlp->nlp_type |= NLP_FABRIC;
4196+
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
4197+
4198+
out:
4199+
lpfc_mbuf_free(phba, mp->virt, mp->phys);
4200+
kfree(mp);
4201+
mempool_free(pmb, phba->mbox_mem_pool);
4202+
4203+
/* Drop the reference count from the mbox at the end after
4204+
* all the current reference to the ndlp have been done.
4205+
*/
4206+
lpfc_nlp_put(ndlp);
4207+
}
4208+
41634209
static void
41644210
lpfc_register_remote_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
41654211
{

drivers/scsi/lpfc/lpfc_nportdisc.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,15 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
785785
else
786786
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
787787

788+
/* This clause allows the initiator to ACC the LOGO back to the
789+
* Fabric Domain Controller. It does deliberately skip all other
790+
* steps because some fabrics send RDP requests after logging out
791+
* from the initiator.
792+
*/
793+
if (ndlp->nlp_type & NLP_FABRIC &&
794+
((ndlp->nlp_DID & WELL_KNOWN_DID_MASK) != WELL_KNOWN_DID_MASK))
795+
return 0;
796+
788797
/* Notify transport of connectivity loss to trigger cleanup. */
789798
if (phba->nvmet_support &&
790799
ndlp->nlp_state == NLP_STE_UNMAPPED_NODE)
@@ -1423,6 +1432,8 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
14231432
switch (ndlp->nlp_DID) {
14241433
case NameServer_DID:
14251434
mbox->mbox_cmpl = lpfc_mbx_cmpl_ns_reg_login;
1435+
/* Fabric Controller Node needs these parameters. */
1436+
memcpy(&ndlp->fc_sparam, sp, sizeof(struct serv_parm));
14261437
break;
14271438
case FDMI_DID:
14281439
mbox->mbox_cmpl = lpfc_mbx_cmpl_fdmi_reg_login;

drivers/scsi/lpfc/lpfc_sli.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2755,7 +2755,6 @@ lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
27552755
} else {
27562756
__lpfc_sli_rpi_release(vport, ndlp);
27572757
}
2758-
27592758
lpfc_nlp_put(ndlp);
27602759
}
27612760
}

0 commit comments

Comments
 (0)