Probe failure and removal leave SDHCI child devices registered after the
parent clock and managed resources are released.
Unregister the OF children in reverse order before disabling the parent
clock on both paths. Use of_platform_device_destroy() because manual
child creation does not set the flag required by of_platform_depopulate().
This issue was identified during our ongoing static-analysis research
while reviewing kernel code.
Fixes: bb7b8ec62dfb ("mmc: sdhci-of-aspeed: Add support for the ASPEED SD controller")
Co-developed-by: Ijae Kim <redacted>
Signed-off-by: Ijae Kim <redacted>
Signed-off-by: Myeonghun Pak <redacted>
Assisted-by: OpenAI:GPT-5.6
---
Validated with an ARM64 W=1 object build and strict checkpatch.
No hardware runtime, probe-failure injection or unbind testing was done.
drivers/mmc/host/sdhci-of-aspeed.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/host/sdhci-of-aspeed.c b/drivers/mmc/host/sdhci-of-aspeed.c
index f5d973783c..d317626feb 100644
--- a/drivers/mmc/host/sdhci-of-aspeed.c
+++ b/drivers/mmc/host/sdhci-of-aspeed.c
@@ -560,12 +560,14 @@ static int aspeed_sdc_probe(struct platform_device *pdev)
cpdev = of_platform_device_create(child, NULL, &pdev->dev);
if (!cpdev) {
ret = -ENODEV;
- goto err_clk;
+ goto err_children;
}
}
return 0;
+err_children:
+ device_for_each_child_reverse(&pdev->dev, NULL, of_platform_device_destroy);
err_clk:
clk_disable_unprepare(sdc->clk);
return ret;@@ -575,6 +577,7 @@ static void aspeed_sdc_remove(struct platform_device *pdev)
{
struct aspeed_sdc *sdc = dev_get_drvdata(&pdev->dev);
+ device_for_each_child_reverse(&pdev->dev, NULL, of_platform_device_destroy);
clk_disable_unprepare(sdc->clk);
}
--
2.50.1