]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
scsi: lpfc: Call lpfc_sli4_queue_unset() in restart and rmmod paths
authorJustin Tee <justin.tee@broadcom.com>
Thu, 31 Oct 2024 22:32:11 +0000 (15:32 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Sun, 3 Nov 2024 01:45:24 +0000 (21:45 -0400)
During initialization, the driver allocates wq->pring in lpfc_wq_create
and lpfc_sli4_queue_unset() is the only place where kfree(wq->pring) is
called.

There is a possible memory leak in lpfc_sli_brdrestart_s4() (restart)
and lpfc_pci_remove_one_s4() (rmmod) paths because there are no calls to
lpfc_sli4_queue_unset() to kfree() the wq->pring.

Fix by inserting a call to lpfc_sli4_queue_unset() in
lpfc_sli_brdrestart_s4() and lpfc_sli4_hba_unset() routines.  Also, add
a check for the SLI_ACTIVE flag before issuing the Q_DESTROY mailbox
command.  If not set, then the mailbox command will obviously fail.  In
such cases, skip issuing the mailbox command and only execute the driver
resource clean up portions of the lpfc_*q_destroy routines.

Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://lore.kernel.org/r/20241031223219.152342-4-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_sli.c

index 0dd451009b07914450dc70f2c981b690557c1d8c..a3658ef1141b265a0ef223f995b878ebcd45ad5d 100644 (file)
@@ -13518,6 +13518,8 @@ lpfc_sli4_hba_unset(struct lpfc_hba *phba)
        /* Disable FW logging to host memory */
        lpfc_ras_stop_fwlog(phba);
 
+       lpfc_sli4_queue_unset(phba);
+
        /* Reset SLI4 HBA FCoE function */
        lpfc_pci_function_reset(phba);
 
index 80a43fd40af26e52a2fe8c3cd723814035ead275..5ad5ff10256b6d741d8f3237cdb590768da72ca2 100644 (file)
@@ -5293,6 +5293,8 @@ lpfc_sli_brdrestart_s4(struct lpfc_hba *phba)
                        "0296 Restart HBA Data: x%x x%x\n",
                        phba->pport->port_state, psli->sli_flag);
 
+       lpfc_sli4_queue_unset(phba);
+
        rc = lpfc_sli4_brdreset(phba);
        if (rc) {
                phba->link_state = LPFC_HBA_ERROR;
@@ -17627,6 +17629,9 @@ lpfc_eq_destroy(struct lpfc_hba *phba, struct lpfc_queue *eq)
        if (!eq)
                return -ENODEV;
 
+       if (!(phba->sli.sli_flag & LPFC_SLI_ACTIVE))
+               goto list_remove;
+
        mbox = mempool_alloc(eq->phba->mbox_mem_pool, GFP_KERNEL);
        if (!mbox)
                return -ENOMEM;
@@ -17653,10 +17658,12 @@ lpfc_eq_destroy(struct lpfc_hba *phba, struct lpfc_queue *eq)
                                shdr_status, shdr_add_status, rc);
                status = -ENXIO;
        }
+       mempool_free(mbox, eq->phba->mbox_mem_pool);
 
+list_remove:
        /* Remove eq from any list */
        list_del_init(&eq->list);
-       mempool_free(mbox, eq->phba->mbox_mem_pool);
+
        return status;
 }
 
@@ -17684,6 +17691,10 @@ lpfc_cq_destroy(struct lpfc_hba *phba, struct lpfc_queue *cq)
        /* sanity check on queue memory */
        if (!cq)
                return -ENODEV;
+
+       if (!(phba->sli.sli_flag & LPFC_SLI_ACTIVE))
+               goto list_remove;
+
        mbox = mempool_alloc(cq->phba->mbox_mem_pool, GFP_KERNEL);
        if (!mbox)
                return -ENOMEM;
@@ -17709,9 +17720,11 @@ lpfc_cq_destroy(struct lpfc_hba *phba, struct lpfc_queue *cq)
                                shdr_status, shdr_add_status, rc);
                status = -ENXIO;
        }
+       mempool_free(mbox, cq->phba->mbox_mem_pool);
+
+list_remove:
        /* Remove cq from any list */
        list_del_init(&cq->list);
-       mempool_free(mbox, cq->phba->mbox_mem_pool);
        return status;
 }
 
@@ -17739,6 +17752,10 @@ lpfc_mq_destroy(struct lpfc_hba *phba, struct lpfc_queue *mq)
        /* sanity check on queue memory */
        if (!mq)
                return -ENODEV;
+
+       if (!(phba->sli.sli_flag & LPFC_SLI_ACTIVE))
+               goto list_remove;
+
        mbox = mempool_alloc(mq->phba->mbox_mem_pool, GFP_KERNEL);
        if (!mbox)
                return -ENOMEM;
@@ -17764,9 +17781,11 @@ lpfc_mq_destroy(struct lpfc_hba *phba, struct lpfc_queue *mq)
                                shdr_status, shdr_add_status, rc);
                status = -ENXIO;
        }
+       mempool_free(mbox, mq->phba->mbox_mem_pool);
+
+list_remove:
        /* Remove mq from any list */
        list_del_init(&mq->list);
-       mempool_free(mbox, mq->phba->mbox_mem_pool);
        return status;
 }
 
@@ -17794,6 +17813,10 @@ lpfc_wq_destroy(struct lpfc_hba *phba, struct lpfc_queue *wq)
        /* sanity check on queue memory */
        if (!wq)
                return -ENODEV;
+
+       if (!(phba->sli.sli_flag & LPFC_SLI_ACTIVE))
+               goto list_remove;
+
        mbox = mempool_alloc(wq->phba->mbox_mem_pool, GFP_KERNEL);
        if (!mbox)
                return -ENOMEM;
@@ -17818,11 +17841,13 @@ lpfc_wq_destroy(struct lpfc_hba *phba, struct lpfc_queue *wq)
                                shdr_status, shdr_add_status, rc);
                status = -ENXIO;
        }
+       mempool_free(mbox, wq->phba->mbox_mem_pool);
+
+list_remove:
        /* Remove wq from any list */
        list_del_init(&wq->list);
        kfree(wq->pring);
        wq->pring = NULL;
-       mempool_free(mbox, wq->phba->mbox_mem_pool);
        return status;
 }
 
@@ -17852,6 +17877,10 @@ lpfc_rq_destroy(struct lpfc_hba *phba, struct lpfc_queue *hrq,
        /* sanity check on queue memory */
        if (!hrq || !drq)
                return -ENODEV;
+
+       if (!(phba->sli.sli_flag & LPFC_SLI_ACTIVE))
+               goto list_remove;
+
        mbox = mempool_alloc(hrq->phba->mbox_mem_pool, GFP_KERNEL);
        if (!mbox)
                return -ENOMEM;
@@ -17892,9 +17921,11 @@ lpfc_rq_destroy(struct lpfc_hba *phba, struct lpfc_queue *hrq,
                                shdr_status, shdr_add_status, rc);
                status = -ENXIO;
        }
+       mempool_free(mbox, hrq->phba->mbox_mem_pool);
+
+list_remove:
        list_del_init(&hrq->list);
        list_del_init(&drq->list);
-       mempool_free(mbox, hrq->phba->mbox_mem_pool);
        return status;
 }