]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
scsi: ufs: pltfrm: Disable runtime PM during removal of glue drivers
authorManivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Mon, 11 Nov 2024 17:48:32 +0000 (23:18 +0530)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 21 Nov 2024 03:03:05 +0000 (22:03 -0500)
When the UFSHCD platform glue drivers are removed, runtime PM should be
disabled using pm_runtime_disable() to balance the enablement done in
ufshcd_pltfrm_init(). This is also reported by PM core when the glue driver
is removed and inserted again:

ufshcd-qcom 1d84000.ufshc: Unbalanced pm_runtime_enable!

So disable runtime PM using a new helper API ufshcd_pltfrm_remove(), that
also takes care of removing ufshcd. This helper should be called during the
remove() stage of glue drivers.

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-3-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>
drivers/ufs/host/cdns-pltfrm.c
drivers/ufs/host/tc-dwc-g210-pltfrm.c
drivers/ufs/host/ufs-exynos.c
drivers/ufs/host/ufs-hisi.c
drivers/ufs/host/ufs-mediatek.c
drivers/ufs/host/ufs-qcom.c
drivers/ufs/host/ufs-renesas.c
drivers/ufs/host/ufs-sprd.c
drivers/ufs/host/ufshcd-pltfrm.c
drivers/ufs/host/ufshcd-pltfrm.h

index 66811d8d1929c135aa43d5cda482464cf37854b4..b31aa84111511bf2d1e2fcb7cf0a90ac14dd076c 100644 (file)
@@ -307,9 +307,7 @@ static int cdns_ufs_pltfrm_probe(struct platform_device *pdev)
  */
 static void cdns_ufs_pltfrm_remove(struct platform_device *pdev)
 {
-       struct ufs_hba *hba =  platform_get_drvdata(pdev);
-
-       ufshcd_remove(hba);
+       ufshcd_pltfrm_remove(pdev);
 }
 
 static const struct dev_pm_ops cdns_ufs_dev_pm_ops = {
index a3877592604d5d659add23f18f1c93c22ef99341..113e0ef7b2cf84d212ae3bff0181aee9db6926a3 100644 (file)
@@ -76,10 +76,8 @@ static int tc_dwc_g210_pltfm_probe(struct platform_device *pdev)
  */
 static void tc_dwc_g210_pltfm_remove(struct platform_device *pdev)
 {
-       struct ufs_hba *hba =  platform_get_drvdata(pdev);
-
        pm_runtime_get_sync(&(pdev)->dev);
-       ufshcd_remove(hba);
+       ufshcd_pltfrm_remove(pdev);
 }
 
 static const struct dev_pm_ops tc_dwc_g210_pltfm_pm_ops = {
index 91827b3e582bb92dcf0125fd0d27047a9baef214..b20f6526777a7f215ccca1dc557e6396151c9a93 100644 (file)
@@ -1993,7 +1993,7 @@ static void exynos_ufs_remove(struct platform_device *pdev)
        struct exynos_ufs *ufs = ufshcd_get_variant(hba);
 
        pm_runtime_get_sync(&(pdev)->dev);
-       ufshcd_remove(hba);
+       ufshcd_pltfrm_remove(pdev);
 
        phy_power_off(ufs->phy);
        phy_exit(ufs->phy);
index 5ee73ff052512b3468adc707ed26e99cd8c3b1ec..501609521b2609077f0688c130aa1bbef39ed784 100644 (file)
@@ -576,9 +576,7 @@ static int ufs_hisi_probe(struct platform_device *pdev)
 
 static void ufs_hisi_remove(struct platform_device *pdev)
 {
-       struct ufs_hba *hba =  platform_get_drvdata(pdev);
-
-       ufshcd_remove(hba);
+       ufshcd_pltfrm_remove(pdev);
 }
 
 static const struct dev_pm_ops ufs_hisi_pm_ops = {
index 06ab1e5e8b6fbc2dd67d18cd7832f5e4d6c87b29..b444146419dea87ba1b79b46870eb7f8fa7cbc45 100644 (file)
@@ -1879,10 +1879,8 @@ out:
  */
 static void ufs_mtk_remove(struct platform_device *pdev)
 {
-       struct ufs_hba *hba =  platform_get_drvdata(pdev);
-
        pm_runtime_get_sync(&(pdev)->dev);
-       ufshcd_remove(hba);
+       ufshcd_pltfrm_remove(pdev);
 }
 
 #ifdef CONFIG_PM_SLEEP
index 5220ec78021d61a4eed177d41ad10fbf8e6be383..3762337d75765f342788fa71ffa15c5c9127b0c7 100644 (file)
@@ -1864,7 +1864,7 @@ static void ufs_qcom_remove(struct platform_device *pdev)
        struct ufs_qcom_host *host = ufshcd_get_variant(hba);
 
        pm_runtime_get_sync(&(pdev)->dev);
-       ufshcd_remove(hba);
+       ufshcd_pltfrm_remove(pdev);
        if (host->esi_enabled)
                platform_device_msi_free_irqs_all(hba->dev);
 }
index 3ff97112e1f6d085b59972643a78c3ebc061c24e..21a64b34397d8c64736440f30812a35aedeb1027 100644 (file)
@@ -397,9 +397,7 @@ static int ufs_renesas_probe(struct platform_device *pdev)
 
 static void ufs_renesas_remove(struct platform_device *pdev)
 {
-       struct ufs_hba *hba = platform_get_drvdata(pdev);
-
-       ufshcd_remove(hba);
+       ufshcd_pltfrm_remove(pdev);
 }
 
 static struct platform_driver ufs_renesas_platform = {
index d8b165908809d69a7ca6bdd82f07ffc87db9def4..e455890cf7d49e3e49ffb2e4c7f840c62d7d7e2c 100644 (file)
@@ -427,10 +427,8 @@ static int ufs_sprd_probe(struct platform_device *pdev)
 
 static void ufs_sprd_remove(struct platform_device *pdev)
 {
-       struct ufs_hba *hba =  platform_get_drvdata(pdev);
-
        pm_runtime_get_sync(&(pdev)->dev);
-       ufshcd_remove(hba);
+       ufshcd_pltfrm_remove(pdev);
 }
 
 static const struct dev_pm_ops ufs_sprd_pm_ops = {
index 1f4f30d6cb42343da61c800530ae247d9d6f78c6..bad5b1303eb685ce9d7ae36609104ff0b859fb79 100644 (file)
@@ -524,6 +524,19 @@ out:
 }
 EXPORT_SYMBOL_GPL(ufshcd_pltfrm_init);
 
+/**
+ * ufshcd_pltfrm_remove - Remove ufshcd platform
+ * @pdev: pointer to Platform device handle
+ */
+void ufshcd_pltfrm_remove(struct platform_device *pdev)
+{
+       struct ufs_hba *hba =  platform_get_drvdata(pdev);
+
+       ufshcd_remove(hba);
+       pm_runtime_disable(&pdev->dev);
+}
+EXPORT_SYMBOL_GPL(ufshcd_pltfrm_remove);
+
 MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
 MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
 MODULE_DESCRIPTION("UFS host controller Platform bus based glue driver");
index df387be5216bd42f6d3adb66761bb9200904960d..3017f8e8f93c678bf4071924ed2ef54395354a5f 100644 (file)
@@ -31,6 +31,7 @@ int ufshcd_negotiate_pwr_params(const struct ufs_host_params *host_params,
 void ufshcd_init_host_params(struct ufs_host_params *host_params);
 int ufshcd_pltfrm_init(struct platform_device *pdev,
                       const struct ufs_hba_variant_ops *vops);
+void ufshcd_pltfrm_remove(struct platform_device *pdev);
 int ufshcd_populate_vreg(struct device *dev, const char *name,
                         struct ufs_vreg **out_vreg, bool skip_current);