Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi: ufs: pltfrm: Drop PM runtime reference count after ufshcd_remove()

During the remove stage of glue drivers, some of them are incrementing the
reference count using pm_runtime_get_sync(), before removing the ufshcd
using ufshcd_remove(). But they are not dropping that reference count after
ufshcd_remove() to balance the refcount.

So drop the reference count by calling pm_runtime_put_noidle() after
ufshcd_remove(). Since the behavior is applicable to all glue drivers, move
the PM handling to ufshcd_pltfrm_remove().

Cc: stable@vger.kernel.org # 3.12
Fixes: 62694735ca95 ("[SCSI] ufs: Add runtime PM support for UFS host controller driver")
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Link: https://lore.kernel.org/r/20241111-ufs_bug_fix-v1-4-45ad8b62f02e@linaro.org
Reviewed-by: Peter Wang <peter.wang@mediatek.com>
Reviewed-by: Bean Huo <beanhuo@micron.com>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Manivannan Sadhasivam and committed by
Martin K. Petersen
1745dcdb d3326e6a

+2 -5
-1
drivers/ufs/host/tc-dwc-g210-pltfrm.c
··· 76 76 */ 77 77 static void tc_dwc_g210_pltfm_remove(struct platform_device *pdev) 78 78 { 79 - pm_runtime_get_sync(&(pdev)->dev); 80 79 ufshcd_pltfrm_remove(pdev); 81 80 } 82 81
-1
drivers/ufs/host/ufs-exynos.c
··· 1992 1992 struct ufs_hba *hba = platform_get_drvdata(pdev); 1993 1993 struct exynos_ufs *ufs = ufshcd_get_variant(hba); 1994 1994 1995 - pm_runtime_get_sync(&(pdev)->dev); 1996 1995 ufshcd_pltfrm_remove(pdev); 1997 1996 1998 1997 phy_power_off(ufs->phy);
-1
drivers/ufs/host/ufs-mediatek.c
··· 1879 1879 */ 1880 1880 static void ufs_mtk_remove(struct platform_device *pdev) 1881 1881 { 1882 - pm_runtime_get_sync(&(pdev)->dev); 1883 1882 ufshcd_pltfrm_remove(pdev); 1884 1883 } 1885 1884
-1
drivers/ufs/host/ufs-qcom.c
··· 1863 1863 struct ufs_hba *hba = platform_get_drvdata(pdev); 1864 1864 struct ufs_qcom_host *host = ufshcd_get_variant(hba); 1865 1865 1866 - pm_runtime_get_sync(&(pdev)->dev); 1867 1866 ufshcd_pltfrm_remove(pdev); 1868 1867 if (host->esi_enabled) 1869 1868 platform_device_msi_free_irqs_all(hba->dev);
-1
drivers/ufs/host/ufs-sprd.c
··· 427 427 428 428 static void ufs_sprd_remove(struct platform_device *pdev) 429 429 { 430 - pm_runtime_get_sync(&(pdev)->dev); 431 430 ufshcd_pltfrm_remove(pdev); 432 431 } 433 432
+2
drivers/ufs/host/ufshcd-pltfrm.c
··· 532 532 { 533 533 struct ufs_hba *hba = platform_get_drvdata(pdev); 534 534 535 + pm_runtime_get_sync(&pdev->dev); 535 536 ufshcd_remove(hba); 536 537 pm_runtime_disable(&pdev->dev); 538 + pm_runtime_put_noidle(&pdev->dev); 537 539 } 538 540 EXPORT_SYMBOL_GPL(ufshcd_pltfrm_remove); 539 541