| From stable+bounces-196542-greg=kroah.com@vger.kernel.org Fri Nov 21 18:16:12 2025 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 21 Nov 2025 12:16:05 -0500 |
| Subject: pmdomain: arm: scmi: Fix genpd leak on provider registration failure |
| To: stable@vger.kernel.org |
| Cc: Sudeep Holla <sudeep.holla@arm.com>, Peng Fan <peng.fan@nxp.com>, Ulf Hansson <ulf.hansson@linaro.org>, Sasha Levin <sashal@kernel.org> |
| Message-ID: <20251121171605.2611489-1-sashal@kernel.org> |
| |
| From: Sudeep Holla <sudeep.holla@arm.com> |
| |
| [ Upstream commit 7458f72cc28f9eb0de811effcb5376d0ec19094a ] |
| |
| If of_genpd_add_provider_onecell() fails during probe, the previously |
| created generic power domains are not removed, leading to a memory leak |
| and potential kernel crash later in genpd_debug_add(). |
| |
| Add proper error handling to unwind the initialized domains before |
| returning from probe to ensure all resources are correctly released on |
| failure. |
| |
| Example crash trace observed without this fix: |
| |
| | Unable to handle kernel paging request at virtual address fffffffffffffc70 |
| | CPU: 1 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.18.0-rc1 #405 PREEMPT |
| | Hardware name: ARM LTD ARM Juno Development Platform/ARM Juno Development Platform |
| | pstate: 00000005 (nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) |
| | pc : genpd_debug_add+0x2c/0x160 |
| | lr : genpd_debug_init+0x74/0x98 |
| | Call trace: |
| | genpd_debug_add+0x2c/0x160 (P) |
| | genpd_debug_init+0x74/0x98 |
| | do_one_initcall+0xd0/0x2d8 |
| | do_initcall_level+0xa0/0x140 |
| | do_initcalls+0x60/0xa8 |
| | do_basic_setup+0x28/0x40 |
| | kernel_init_freeable+0xe8/0x170 |
| | kernel_init+0x2c/0x140 |
| | ret_from_fork+0x10/0x20 |
| |
| Fixes: 898216c97ed2 ("firmware: arm_scmi: add device power domain support using genpd") |
| Signed-off-by: Sudeep Holla <sudeep.holla@arm.com> |
| Reviewed-by: Peng Fan <peng.fan@nxp.com> |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> |
| [ drivers/pmdomain/arm/scmi_pm_domain.c -> drivers/firmware/arm_scmi/scmi_pm_domain.c ] |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/firmware/arm_scmi/scmi_pm_domain.c | 13 +++++++++++-- |
| 1 file changed, 11 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/firmware/arm_scmi/scmi_pm_domain.c |
| +++ b/drivers/firmware/arm_scmi/scmi_pm_domain.c |
| @@ -53,7 +53,7 @@ static int scmi_pd_power_off(struct gene |
| |
| static int scmi_pm_domain_probe(struct scmi_device *sdev) |
| { |
| - int num_domains, i; |
| + int num_domains, i, ret; |
| struct device *dev = &sdev->dev; |
| struct device_node *np = dev->of_node; |
| struct scmi_pm_domain *scmi_pd; |
| @@ -106,9 +106,18 @@ static int scmi_pm_domain_probe(struct s |
| scmi_pd_data->domains = domains; |
| scmi_pd_data->num_domains = num_domains; |
| |
| + ret = of_genpd_add_provider_onecell(np, scmi_pd_data); |
| + if (ret) |
| + goto err_rm_genpds; |
| + |
| dev_set_drvdata(dev, scmi_pd_data); |
| |
| - return of_genpd_add_provider_onecell(np, scmi_pd_data); |
| + return 0; |
| +err_rm_genpds: |
| + for (i = num_domains - 1; i >= 0; i--) |
| + pm_genpd_remove(domains[i]); |
| + |
| + return ret; |
| } |
| |
| static void scmi_pm_domain_remove(struct scmi_device *sdev) |