[PATCH] pmdomain: arm: scmi: Fix genpd leak on provider registration failure

Ulf Hansson ulf.hansson at linaro.org
Wed Oct 22 07:18:07 PDT 2025


On Fri, 17 Oct 2025 at 13:03, Sudeep Holla <sudeep.holla at arm.com> wrote:
>
> 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 at arm.com>

Applied for fixes and by adding a stable tag, thanks!

Kind regards
Uffe

> ---
>  drivers/pmdomain/arm/scmi_pm_domain.c | 13 +++++++++++--
>  1 file changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/pmdomain/arm/scmi_pm_domain.c b/drivers/pmdomain/arm/scmi_pm_domain.c
> index 8fe1c0a501c9..b5e2ffd5ea64 100644
> --- a/drivers/pmdomain/arm/scmi_pm_domain.c
> +++ b/drivers/pmdomain/arm/scmi_pm_domain.c
> @@ -41,7 +41,7 @@ static int scmi_pd_power_off(struct generic_pm_domain *domain)
>
>  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;
> @@ -108,9 +108,18 @@ static int scmi_pm_domain_probe(struct scmi_device *sdev)
>         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)
> --
> 2.34.1
>



More information about the linux-arm-kernel mailing list