Skip to content

Commit 0b8b15a

Browse files
Justin Teemartinkpetersen
authored andcommitted
scsi: lpfc: Modify kref handling for Fabric Controller ndlps
Currently, there is a kref put in the lpfc_cleanup() routine that takes care of outstanding references on fabric controller ndlps in UNUSED state. While typically there is a state change from UNUSED -> REGLOGIN when the ndlp successfully logs into the fabric, there may be cases when FLOGI is unsuccessful and the ndlp will remain in UNUSED state without a registered rpi, yet the ndlp incorrectly has a kref count of one. To address this, handling of Fabric Controller ndlps are moved into the routines: lpfc_issue_els_scr(), lpfc_issue_els_rdf(), lpfc_cmpl_els_disc_cmd(). In both lpfc_issue_els_scr() and lpfc_issue_els_rdf(), if there does not exist a previously created fabric controller ndlp, an ndlp will be created. Otherwise, we can reuse the pre-existing ndlp object. In lpfc_cmpl_els_disc_cmd(), if the SCR or RDF are not successfully issued, the initial reference on the ndlp that is not registered with upper layers will be decremented with a kref_put(). Signed-off-by: Justin Tee <justin.tee@broadcom.com> Link: https://patch.msgid.link/20251106224639.139176-7-justintee8345@gmail.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 23f4906 commit 0b8b15a

2 files changed

Lines changed: 67 additions & 36 deletions

File tree

drivers/scsi/lpfc/lpfc_els.c

Lines changed: 67 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3390,11 +3390,21 @@ lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
33903390
lpfc_cmpl_els_edc(phba, cmdiocb, rspiocb);
33913391
return;
33923392
}
3393+
33933394
if (ulp_status) {
33943395
/* ELS discovery cmd completes with error */
33953396
lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS | LOG_CGN_MGMT,
33963397
"4203 ELS cmd x%x error: x%x x%X\n", cmd,
33973398
ulp_status, ulp_word4);
3399+
3400+
/* In the case where the ELS cmd completes with an error and
3401+
* the node does not have RPI registered, the node is
3402+
* outstanding and should put its initial reference.
3403+
*/
3404+
if ((cmd == ELS_CMD_SCR || cmd == ELS_CMD_RDF) &&
3405+
!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD) &&
3406+
!test_and_set_bit(NLP_DROPPED, &ndlp->nlp_flag))
3407+
lpfc_nlp_put(ndlp);
33983408
goto out;
33993409
}
34003410

@@ -3463,6 +3473,7 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
34633473
uint8_t *pcmd;
34643474
uint16_t cmdsize;
34653475
struct lpfc_nodelist *ndlp;
3476+
bool node_created = false;
34663477

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

@@ -3472,21 +3483,21 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
34723483
if (!ndlp)
34733484
return 1;
34743485
lpfc_enqueue_node(vport, ndlp);
3486+
node_created = true;
34753487
}
34763488

34773489
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
34783490
ndlp->nlp_DID, ELS_CMD_SCR);
34793491
if (!elsiocb)
3480-
return 1;
3492+
goto out_node_created;
34813493

34823494
if (phba->sli_rev == LPFC_SLI_REV4) {
34833495
rc = lpfc_reg_fab_ctrl_node(vport, ndlp);
34843496
if (rc) {
3485-
lpfc_els_free_iocb(phba, elsiocb);
34863497
lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
34873498
"0937 %s: Failed to reg fc node, rc %d\n",
34883499
__func__, rc);
3489-
return 1;
3500+
goto out_free_iocb;
34903501
}
34913502
}
34923503
pcmd = (uint8_t *)elsiocb->cmd_dmabuf->virt;
@@ -3505,23 +3516,27 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry)
35053516
phba->fc_stat.elsXmitSCR++;
35063517
elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd;
35073518
elsiocb->ndlp = lpfc_nlp_get(ndlp);
3508-
if (!elsiocb->ndlp) {
3509-
lpfc_els_free_iocb(phba, elsiocb);
3510-
return 1;
3511-
}
3519+
if (!elsiocb->ndlp)
3520+
goto out_free_iocb;
35123521

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

35173526
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
3518-
if (rc == IOCB_ERROR) {
3519-
lpfc_els_free_iocb(phba, elsiocb);
3520-
lpfc_nlp_put(ndlp);
3521-
return 1;
3522-
}
3527+
if (rc == IOCB_ERROR)
3528+
goto out_iocb_error;
35233529

35243530
return 0;
3531+
3532+
out_iocb_error:
3533+
lpfc_nlp_put(ndlp);
3534+
out_free_iocb:
3535+
lpfc_els_free_iocb(phba, elsiocb);
3536+
out_node_created:
3537+
if (node_created)
3538+
lpfc_nlp_put(ndlp);
3539+
return 1;
35253540
}
35263541

35273542
/**
@@ -3734,7 +3749,12 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
37343749
*
37353750
* Return code
37363751
* 0 - Successfully issued rdf command
3737-
* 1 - Failed to issue rdf command
3752+
* < 0 - Failed to issue rdf command
3753+
* -EACCES - RDF not required for NPIV_PORT
3754+
* -ENODEV - No fabric controller device available
3755+
* -ENOMEM - No available memory
3756+
* -EIO - The mailbox failed to complete successfully.
3757+
*
37383758
**/
37393759
int
37403760
lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
@@ -3745,25 +3765,30 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
37453765
struct lpfc_nodelist *ndlp;
37463766
uint16_t cmdsize;
37473767
int rc;
3768+
bool node_created = false;
3769+
int err;
37483770

37493771
cmdsize = sizeof(*prdf);
37503772

3773+
/* RDF ELS is not required on an NPIV VN_Port. */
3774+
if (vport->port_type == LPFC_NPIV_PORT)
3775+
return -EACCES;
3776+
37513777
ndlp = lpfc_findnode_did(vport, Fabric_Cntl_DID);
37523778
if (!ndlp) {
37533779
ndlp = lpfc_nlp_init(vport, Fabric_Cntl_DID);
37543780
if (!ndlp)
37553781
return -ENODEV;
37563782
lpfc_enqueue_node(vport, ndlp);
3783+
node_created = true;
37573784
}
37583785

3759-
/* RDF ELS is not required on an NPIV VN_Port. */
3760-
if (vport->port_type == LPFC_NPIV_PORT)
3761-
return -EACCES;
3762-
37633786
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
37643787
ndlp->nlp_DID, ELS_CMD_RDF);
3765-
if (!elsiocb)
3766-
return -ENOMEM;
3788+
if (!elsiocb) {
3789+
err = -ENOMEM;
3790+
goto out_node_created;
3791+
}
37673792

37683793
/* Configure the payload for the supported FPIN events. */
37693794
prdf = (struct lpfc_els_rdf_req *)elsiocb->cmd_dmabuf->virt;
@@ -3789,8 +3814,8 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
37893814
elsiocb->cmd_cmpl = lpfc_cmpl_els_disc_cmd;
37903815
elsiocb->ndlp = lpfc_nlp_get(ndlp);
37913816
if (!elsiocb->ndlp) {
3792-
lpfc_els_free_iocb(phba, elsiocb);
3793-
return -EIO;
3817+
err = -EIO;
3818+
goto out_free_iocb;
37943819
}
37953820

37963821
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
@@ -3799,11 +3824,19 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
37993824

38003825
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
38013826
if (rc == IOCB_ERROR) {
3802-
lpfc_els_free_iocb(phba, elsiocb);
3803-
lpfc_nlp_put(ndlp);
3804-
return -EIO;
3827+
err = -EIO;
3828+
goto out_iocb_error;
38053829
}
38063830
return 0;
3831+
3832+
out_iocb_error:
3833+
lpfc_nlp_put(ndlp);
3834+
out_free_iocb:
3835+
lpfc_els_free_iocb(phba, elsiocb);
3836+
out_node_created:
3837+
if (node_created)
3838+
lpfc_nlp_put(ndlp);
3839+
return err;
38073840
}
38083841

38093842
/**
@@ -3824,19 +3857,23 @@ static int
38243857
lpfc_els_rcv_rdf(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
38253858
struct lpfc_nodelist *ndlp)
38263859
{
3860+
int rc;
3861+
3862+
rc = lpfc_els_rsp_acc(vport, ELS_CMD_RDF, cmdiocb, ndlp, NULL);
38273863
/* Send LS_ACC */
3828-
if (lpfc_els_rsp_acc(vport, ELS_CMD_RDF, cmdiocb, ndlp, NULL)) {
3864+
if (rc) {
38293865
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
3830-
"1623 Failed to RDF_ACC from x%x for x%x\n",
3831-
ndlp->nlp_DID, vport->fc_myDID);
3866+
"1623 Failed to RDF_ACC from x%x for x%x Data: %d\n",
3867+
ndlp->nlp_DID, vport->fc_myDID, rc);
38323868
return -EIO;
38333869
}
38343870

3871+
rc = lpfc_issue_els_rdf(vport, 0);
38353872
/* Issue new RDF for reregistering */
3836-
if (lpfc_issue_els_rdf(vport, 0)) {
3873+
if (rc) {
38373874
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
3838-
"2623 Failed to re register RDF for x%x\n",
3839-
vport->fc_myDID);
3875+
"2623 Failed to re register RDF for x%x Data: %d\n",
3876+
vport->fc_myDID, rc);
38403877
return -EIO;
38413878
}
38423879

drivers/scsi/lpfc/lpfc_init.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3057,12 +3057,6 @@ lpfc_cleanup(struct lpfc_vport *vport)
30573057
lpfc_vmid_vport_cleanup(vport);
30583058

30593059
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
3060-
if (ndlp->nlp_DID == Fabric_Cntl_DID &&
3061-
ndlp->nlp_state == NLP_STE_UNUSED_NODE) {
3062-
lpfc_nlp_put(ndlp);
3063-
continue;
3064-
}
3065-
30663060
/* Fabric Ports not in UNMAPPED state are cleaned up in the
30673061
* DEVICE_RM event.
30683062
*/

0 commit comments

Comments
 (0)