[PATCH] scsi: ufs: core: Fix runtime PM reference leak in ufshcd_init()

Wentao Liang posted 1 patch 1 week ago
drivers/ufs/core/ufshcd.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
[PATCH] scsi: ufs: core: Fix runtime PM reference leak in ufshcd_init()
Posted by Wentao Liang 1 week ago
ufshcd_init() calls pm_runtime_get_sync() to hold auto suspend until the
asynchronous scan completes, and that reference is only dropped in
ufshcd_async_scan(). If initialization fails before the scan is
scheduled, no one ever drops it and the device stays runtime resumed.

Route all error paths taken after pm_runtime_get_sync() through a new
out_put_rpm label that drops the reference.

Fixes: 62694735ca95 ("[SCSI] ufs: Add runtime PM support for UFS host controller driver")
Cc: stable@vger.kernel.org
Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
---
 drivers/ufs/core/ufshcd.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index c3f08957d179..6aee54788d29 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -11236,7 +11236,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
 
 	err = ufshcd_link_startup(hba);
 	if (err)
-		goto out_disable;
+		goto out_put_rpm;
 
 	if (hba->mcq_enabled)
 		ufshcd_config_mcq(hba);
@@ -11253,23 +11253,23 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
 	/* Verify device initialization by sending NOP OUT UPIU */
 	err = ufshcd_verify_dev_init(hba);
 	if (err)
-		goto out_disable;
+		goto out_put_rpm;
 
 	/* Initiate UFS initialization, and waiting until completion */
 	err = ufshcd_complete_dev_init(hba);
 	if (err)
-		goto out_disable;
+		goto out_put_rpm;
 
 	err = ufshcd_device_params_init(hba);
 	if (err)
-		goto out_disable;
+		goto out_put_rpm;
 
 	err = ufshcd_post_device_init(hba);
 
 initialized:
 	ufshcd_process_probe_result(hba, probe_start, err);
 	if (err)
-		goto out_disable;
+		goto out_put_rpm;
 
 	ufs_sysfs_add_nodes(hba->dev);
 	hba->dme_qos_sysfs_handle = sysfs_get_dirent(hba->dev->kobj.sd,
@@ -11280,6 +11280,9 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
 	ufshcd_pm_qos_init(hba);
 	return 0;
 
+out_put_rpm:
+	pm_runtime_put_sync(dev);
+
 out_disable:
 	hba->is_irq_enabled = false;
 	ufshcd_hba_exit(hba);
-- 
2.34.1