This is a note to let you know that I've just added the patch titled scsi: ufs: pltfrm: Disable runtime PM during removal of glue drivers to the 6.6-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: scsi-ufs-pltfrm-disable-runtime-pm-during-removal-of.patch and it can be found in the queue-6.6 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit f2020ee0d7f8af71ab3b510729abbc7912be6399 Author: Manivannan Sadhasivam <manivannan.sadhasivam@xxxxxxxxxx> Date: Mon Nov 11 23:18:32 2024 +0530 scsi: ufs: pltfrm: Disable runtime PM during removal of glue drivers [ Upstream commit d3326e6a3f9bf1e075be2201fb704c2fdf19e2b7 ] 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@xxxxxxxxxxxxxxx # 3.12 Fixes: 62694735ca95 ("[SCSI] ufs: Add runtime PM support for UFS host controller driver") Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@xxxxxxxxxx> Link: https://lore.kernel.org/r/20241111-ufs_bug_fix-v1-3-45ad8b62f02e@xxxxxxxxxx Reviewed-by: Peter Wang <peter.wang@xxxxxxxxxxxx> Reviewed-by: Bean Huo <beanhuo@xxxxxxxxxx> Reviewed-by: Bart Van Assche <bvanassche@xxxxxxx> Signed-off-by: Martin K. Petersen <martin.petersen@xxxxxxxxxx> Stable-dep-of: 1745dcdb7227 ("scsi: ufs: pltfrm: Drop PM runtime reference count after ufshcd_remove()") Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/drivers/ufs/host/cdns-pltfrm.c b/drivers/ufs/host/cdns-pltfrm.c index 66811d8d1929c..b31aa84111511 100644 --- a/drivers/ufs/host/cdns-pltfrm.c +++ b/drivers/ufs/host/cdns-pltfrm.c @@ -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 = { diff --git a/drivers/ufs/host/tc-dwc-g210-pltfrm.c b/drivers/ufs/host/tc-dwc-g210-pltfrm.c index a3877592604d5..113e0ef7b2cf8 100644 --- a/drivers/ufs/host/tc-dwc-g210-pltfrm.c +++ b/drivers/ufs/host/tc-dwc-g210-pltfrm.c @@ -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 = { diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c index 25bc11811b4c1..1cca797a00ba0 100644 --- a/drivers/ufs/host/ufs-exynos.c +++ b/drivers/ufs/host/ufs-exynos.c @@ -1611,7 +1611,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); diff --git a/drivers/ufs/host/ufs-hisi.c b/drivers/ufs/host/ufs-hisi.c index 0229ac0a8dbed..ceae0dd1617ed 100644 --- a/drivers/ufs/host/ufs-hisi.c +++ b/drivers/ufs/host/ufs-hisi.c @@ -577,9 +577,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 = { diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c index 1238faec3cc68..49f63b13a040d 100644 --- a/drivers/ufs/host/ufs-mediatek.c +++ b/drivers/ufs/host/ufs-mediatek.c @@ -1750,10 +1750,8 @@ static int ufs_mtk_probe(struct platform_device *pdev) */ 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 diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 1e75368930d99..762b3aa19f31d 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -1926,7 +1926,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); } diff --git a/drivers/ufs/host/ufs-renesas.c b/drivers/ufs/host/ufs-renesas.c index 3ff97112e1f6d..21a64b34397d8 100644 --- a/drivers/ufs/host/ufs-renesas.c +++ b/drivers/ufs/host/ufs-renesas.c @@ -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 = { diff --git a/drivers/ufs/host/ufs-sprd.c b/drivers/ufs/host/ufs-sprd.c index d8b165908809d..e455890cf7d49 100644 --- a/drivers/ufs/host/ufs-sprd.c +++ b/drivers/ufs/host/ufs-sprd.c @@ -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 = { diff --git a/drivers/ufs/host/ufshcd-pltfrm.c b/drivers/ufs/host/ufshcd-pltfrm.c index 797a4dfe45d90..0dc8651eabc22 100644 --- a/drivers/ufs/host/ufshcd-pltfrm.c +++ b/drivers/ufs/host/ufshcd-pltfrm.c @@ -392,6 +392,19 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, } 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@xxxxxxxxxxx>"); MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@xxxxxxxxxxx>"); MODULE_DESCRIPTION("UFS host controller Platform bus based glue driver"); diff --git a/drivers/ufs/host/ufshcd-pltfrm.h b/drivers/ufs/host/ufshcd-pltfrm.h index 2df108f4ac131..1cfc4f8ea07eb 100644 --- a/drivers/ufs/host/ufshcd-pltfrm.h +++ b/drivers/ufs/host/ufshcd-pltfrm.h @@ -31,6 +31,7 @@ int ufshcd_get_pwr_dev_param(const struct ufs_dev_params *dev_param, void ufshcd_init_pwr_dev_param(struct ufs_dev_params *dev_param); 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);