summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Tee <justin.tee@broadcom.com>2024-11-01 01:32:11 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-12-14 22:04:00 +0300
commit78ef7c3909a5be9d3fcf03263e895ac11d6d93a5 (patch)
treedb91f785e3bf01b614aab9a776e568737cb641f4
parent2fcb921c2799c49ac5e365cf4110f94a64ae4885 (diff)
downloadlinux-78ef7c3909a5be9d3fcf03263e895ac11d6d93a5.tar.xz
scsi: lpfc: Call lpfc_sli4_queue_unset() in restart and rmmod paths
[ Upstream commit d35f7672715d1ff3e3ad9bb4ae6ac6cb484200fe ] 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> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c41
2 files changed, 38 insertions, 5 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 0dd451009b07..a3658ef1141b 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -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);
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 2ec6e55771b4..6748fba48a07 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -5291,6 +5291,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;
@@ -17625,6 +17627,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;
@@ -17651,10 +17656,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;
}
@@ -17682,6 +17689,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;
@@ -17707,9 +17718,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;
}
@@ -17737,6 +17750,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;
@@ -17762,9 +17779,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;
}
@@ -17792,6 +17811,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;
@@ -17816,11 +17839,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;
}
@@ -17850,6 +17875,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;
@@ -17890,9 +17919,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;
}