]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
scsi: lpfc: Add REG_VFI mailbox cmd error handling
authorJustin Tee <justin.tee@broadcom.com>
Tue, 31 Mar 2026 20:59:22 +0000 (13:59 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Fri, 3 Apr 2026 01:34:01 +0000 (21:34 -0400)
If lpfc_issue_reg_vfi() returns an error in lpfc_rcv_plogi(), then
execution of lpfc_rcv_plogi() continues and lpfc_reg_rpi() is called, which
allocates an mbuf.  When this REG_RPI mailbox is issued, it inevitably
fails because the VFI is not registered.  However, the REG_RPI failure does
not free the mbuf that was allocated in lpfc_reg_rpi() because there is no
check for mbox error status in lpfc_defer_plogi_acc().

Fix by adding a check in lpfc_rcv_plogi() if lpfc_reg_vfi() fails, then
exit early.  Also, add mailbox status check in lpfc_defer_plogi_acc to
enter the REG_RPI mbox_cmpl functions and free the allocated mbuf.

Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://patch.msgid.link/20260331205928.119833-5-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc_nportdisc.c

index 5e431928de0b179a079538e7cea0e8b525049499..9c449055a55e6f8b1f80e089ea48f78e766f0d60 100644 (file)
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2026 Broadcom. All Rights Reserved. The term *
  * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.     *
  * Copyright (C) 2004-2016 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
@@ -316,8 +316,7 @@ lpfc_defer_plogi_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *login_mbox)
        struct lpfc_iocbq *save_iocb;
        struct lpfc_nodelist *ndlp;
        MAILBOX_t *mb = &login_mbox->u.mb;
-
-       int rc;
+       int rc = 0;
 
        ndlp = login_mbox->ctx_ndlp;
        save_iocb = login_mbox->ctx_u.save_iocb;
@@ -346,7 +345,7 @@ lpfc_defer_plogi_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *login_mbox)
         * completes.  This ensures, in Pt2Pt, that the PLOGI LS_ACC is sent
         * before the PRLI.
         */
-       if (!test_bit(FC_PT2PT, &ndlp->vport->fc_flag)) {
+       if (!test_bit(FC_PT2PT, &ndlp->vport->fc_flag) || mb->mbxStatus || rc) {
                /* Now process the REG_RPI cmpl */
                lpfc_mbx_cmpl_reg_login(phba, login_mbox);
                clear_bit(NLP_ACC_REGLOGIN, &ndlp->nlp_flag);
@@ -525,13 +524,13 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                /* Issue CONFIG_LINK for SLI3 or REG_VFI for SLI4,
                 * to account for updated TOV's / parameters
                 */
-               if (phba->sli_rev == LPFC_SLI_REV4)
-                       lpfc_issue_reg_vfi(vport);
-               else {
+               if (phba->sli_rev == LPFC_SLI_REV4) {
+                       rc = lpfc_issue_reg_vfi(vport);
+               else {
                        link_mbox = mempool_alloc(phba->mbox_mem_pool,
                                                  GFP_KERNEL);
                        if (!link_mbox)
-                               goto out;
+                               goto rsp_rjt;
                        lpfc_config_link(phba, link_mbox);
                        link_mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
                        link_mbox->vport = vport;
@@ -544,11 +543,13 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                        rc = lpfc_sli_issue_mbox(phba, link_mbox, MBX_NOWAIT);
                        if (rc == MBX_NOT_FINISHED) {
                                mempool_free(link_mbox, phba->mbox_mem_pool);
-                               goto out;
+                               goto rsp_rjt;
                        }
                }
 
                lpfc_can_disctmo(vport);
+               if (rc)
+                       goto rsp_rjt;
        }
 
        clear_bit(NLP_SUPPRESS_RSP, &ndlp->nlp_flag);
@@ -562,11 +563,11 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 
        login_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
        if (!login_mbox)
-               goto out;
+               goto rsp_rjt;
 
        save_iocb = kzalloc_obj(*save_iocb);
        if (!save_iocb)
-               goto out;
+               goto free_login_mbox;
 
        /* Save info from cmd IOCB to be used in rsp after all mbox completes */
        memcpy((uint8_t *)save_iocb, (uint8_t *)cmdiocb,
@@ -586,7 +587,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        rc = lpfc_reg_rpi(phba, vport->vpi, remote_did,
                            (uint8_t *)sp, login_mbox, ndlp->nlp_rpi);
        if (rc)
-               goto out;
+               goto free_save_iocb;
 
        login_mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
        login_mbox->vport = vport;
@@ -659,7 +660,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        login_mbox->mbox_cmpl = lpfc_defer_plogi_acc;
        login_mbox->ctx_ndlp = lpfc_nlp_get(ndlp);
        if (!login_mbox->ctx_ndlp)
-               goto out;
+               goto free_save_iocb;
 
        login_mbox->ctx_u.save_iocb = save_iocb; /* For PLOGI ACC */
 
@@ -670,16 +671,17 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        rc = lpfc_sli_issue_mbox(phba, login_mbox, MBX_NOWAIT);
        if (rc == MBX_NOT_FINISHED) {
                lpfc_nlp_put(ndlp);
-               goto out;
+               goto free_save_iocb;
        }
        lpfc_nlp_set_state(vport, ndlp, NLP_STE_REG_LOGIN_ISSUE);
 
        return 1;
-out:
-       kfree(save_iocb);
-       if (login_mbox)
-               mempool_free(login_mbox, phba->mbox_mem_pool);
 
+free_save_iocb:
+       kfree(save_iocb);
+free_login_mbox:
+       mempool_free(login_mbox, phba->mbox_mem_pool);
+rsp_rjt:
        stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
        stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE;
        lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);