Skip to content

Commit 23f4906

Browse files
Justin Teemartinkpetersen
authored andcommitted
scsi: lpfc: Fix leaked ndlp krefs when in point-to-point topology
In point-to-point topology, the driver sometimes defers the unsolicited FLOGI LS_ACC until it sends its FLOGI to the remote port. When this happens, lpfc neglects to release the ndlp allocated for the unsolicited FLOGI. This patch adds code to release the ndlp for the deferred unsolicited FLOGI LS_ACC. An NLP_FLOGI_DFR_ACC flag is introduced to facilitate identifying an ndlp with an expected deferred FLOGI LS_ACC completion. When lpfc_cmpl_els_rsp() detects the correct qualifiers, it releases the initial reference on the ndlp object. And when lpfc_cmpl_els_rsp() exits, the remaining put for the deferred action is executed and the ndlp is released. Signed-off-by: Justin Tee <justin.tee@broadcom.com> Link: https://patch.msgid.link/20251106224639.139176-6-justintee8345@gmail.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 6f81582 commit 23f4906

3 files changed

Lines changed: 49 additions & 20 deletions

File tree

drivers/scsi/lpfc/lpfc.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,6 @@ struct lpfc_defer_flogi_acc {
311311
u16 rx_id;
312312
u16 ox_id;
313313
struct lpfc_nodelist *ndlp;
314-
315314
};
316315

317316
#define LPFC_VMID_TIMER 300 /* timer interval in seconds */

drivers/scsi/lpfc/lpfc_disc.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*******************************************************************
22
* This file is part of the Emulex Linux Device Driver for *
33
* Fibre Channel Host Bus Adapters. *
4-
* Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
4+
* Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
55
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
66
* Copyright (C) 2004-2013 Emulex. All rights reserved. *
77
* EMULEX and SLI are trademarks of Emulex. *
@@ -208,6 +208,7 @@ enum lpfc_nlp_flag {
208208
NPR list */
209209
NLP_RM_DFLT_RPI = 26, /* need to remove leftover dflt RPI */
210210
NLP_NODEV_REMOVE = 27, /* Defer removal till discovery ends */
211+
NLP_FLOGI_DFR_ACC = 28, /* FLOGI LS_ACC was Deferred */
211212
NLP_SC_REQ = 29, /* Target requires authentication */
212213
NLP_FIRSTBURST = 30, /* Target supports FirstBurst */
213214
NLP_RPI_REGISTERED = 31 /* nlp_rpi is valid */

drivers/scsi/lpfc/lpfc_els.c

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,11 +1413,12 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
14131413
phba->defer_flogi_acc.ox_id;
14141414
}
14151415

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

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

1437+
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
1438+
"3354 Xmit deferred FLOGI ACC: rx_id: x%x,"
1439+
" ox_id: x%x, ndlp x%px hba_flag x%lx\n",
1440+
phba->defer_flogi_acc.rx_id,
1441+
phba->defer_flogi_acc.ox_id,
1442+
phba->defer_flogi_acc.ndlp,
1443+
phba->hba_flag);
1444+
14361445
vport->fc_myDID = did;
14371446
}
14381447

@@ -5302,11 +5311,12 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
53025311
IOCB_t *irsp;
53035312
LPFC_MBOXQ_t *mbox = NULL;
53045313
u32 ulp_status, ulp_word4, tmo, did, iotag;
5314+
u32 cmd;
53055315

53065316
if (!vport) {
53075317
lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
53085318
"3177 null vport in ELS rsp\n");
5309-
goto out;
5319+
goto release;
53105320
}
53115321
if (cmdiocb->context_un.mbox)
53125322
mbox = cmdiocb->context_un.mbox;
@@ -5416,7 +5426,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
54165426
* these conditions because it doesn't need the login.
54175427
*/
54185428
if (phba->sli_rev == LPFC_SLI_REV4 &&
5419-
vport && vport->port_type == LPFC_NPIV_PORT &&
5429+
vport->port_type == LPFC_NPIV_PORT &&
54205430
!(ndlp->fc4_xpt_flags & SCSI_XPT_REGD)) {
54215431
if (ndlp->nlp_state != NLP_STE_PLOGI_ISSUE &&
54225432
ndlp->nlp_state != NLP_STE_REG_LOGIN_ISSUE &&
@@ -5432,6 +5442,27 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
54325442
}
54335443
}
54345444

5445+
/* The driver's unsolicited deferred FLOGI ACC in Pt2Pt needs to
5446+
* release the initial reference because the put after the free_iocb
5447+
* call removes only the reference from the defer logic. This FLOGI
5448+
* is never registered with the SCSI transport.
5449+
*/
5450+
if (test_bit(FC_PT2PT, &vport->fc_flag) &&
5451+
test_and_clear_bit(NLP_FLOGI_DFR_ACC, &ndlp->nlp_flag)) {
5452+
lpfc_printf_vlog(vport, KERN_INFO,
5453+
LOG_ELS | LOG_NODE | LOG_DISCOVERY,
5454+
"3357 Pt2Pt Defer FLOGI ACC ndlp x%px, "
5455+
"nflags x%lx, fc_flag x%lx\n",
5456+
ndlp, ndlp->nlp_flag,
5457+
vport->fc_flag);
5458+
cmd = *((u32 *)cmdiocb->cmd_dmabuf->virt);
5459+
if (cmd == ELS_CMD_ACC) {
5460+
if (!test_and_set_bit(NLP_DROPPED, &ndlp->nlp_flag))
5461+
lpfc_nlp_put(ndlp);
5462+
}
5463+
}
5464+
5465+
release:
54355466
/* Release the originating I/O reference. */
54365467
lpfc_els_free_iocb(phba, cmdiocb);
54375468
lpfc_nlp_put(ndlp);
@@ -8399,13 +8430,6 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
83998430
&wqe->xmit_els_rsp.wqe_com);
84008431

84018432
vport->fc_myDID = did;
8402-
8403-
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
8404-
"3344 Deferring FLOGI ACC: rx_id: x%x,"
8405-
" ox_id: x%x, hba_flag x%lx\n",
8406-
phba->defer_flogi_acc.rx_id,
8407-
phba->defer_flogi_acc.ox_id, phba->hba_flag);
8408-
84098433
phba->defer_flogi_acc.flag = true;
84108434

84118435
/* This nlp_get is paired with nlp_puts that reset the
@@ -8414,6 +8438,14 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
84148438
* processed or cancelled.
84158439
*/
84168440
phba->defer_flogi_acc.ndlp = lpfc_nlp_get(ndlp);
8441+
8442+
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
8443+
"3344 Deferring FLOGI ACC: rx_id: x%x,"
8444+
" ox_id: x%x, ndlp x%px, hba_flag x%lx\n",
8445+
phba->defer_flogi_acc.rx_id,
8446+
phba->defer_flogi_acc.ox_id,
8447+
phba->defer_flogi_acc.ndlp,
8448+
phba->hba_flag);
84178449
return 0;
84188450
}
84198451

@@ -10354,11 +10386,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
1035410386
* Do not process any unsolicited ELS commands
1035510387
* if the ndlp is in DEV_LOSS
1035610388
*/
10357-
if (test_bit(NLP_IN_DEV_LOSS, &ndlp->nlp_flag)) {
10358-
if (newnode)
10359-
lpfc_nlp_put(ndlp);
10389+
if (test_bit(NLP_IN_DEV_LOSS, &ndlp->nlp_flag))
1036010390
goto dropit;
10361-
}
1036210391

1036310392
elsiocb->ndlp = lpfc_nlp_get(ndlp);
1036410393
if (!elsiocb->ndlp)

0 commit comments

Comments
 (0)