]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/arm/malidp: use clk_bulk API in runtime PM resume and suspend
authorGustavo Kenji Mendonça Kaneko <kaneko.dev@pm.me>
Tue, 9 Jun 2026 13:08:19 +0000 (13:08 +0000)
committerLiviu Dudau <liviu.dudau@arm.com>
Tue, 30 Jun 2026 14:26:54 +0000 (15:26 +0100)
malidp_runtime_pm_resume() calls clk_prepare_enable() three times
without checking the return value. If any clock fails to enable, the
driver silently proceeds with unclocked hardware, leading to undefined
behavior.

Convert both the resume and suspend paths to use the clk_bulk API:
clk_bulk_prepare_enable() in resume checks the return value and rolls
back any successfully enabled clocks on failure;
clk_bulk_disable_unprepare() in suspend keeps the two paths symmetric.

This issue was found by code review without access to Mali DP hardware.

Signed-off-by: Gustavo Kenji Mendonça Kaneko <kaneko.dev@pm.me>
Reviewed-by: Liviu Dudau <liviu.dudau@arm.com>
Link: https://patch.msgid.link/20260609130812.1065699-1-kaneko.dev@pm.me
Signed-off-by: Liviu Dudau <liviu.dudau@arm.com>
drivers/gpu/drm/arm/malidp_drv.c

index 9abe800f598aca38a65ce45d048884e1904bdf43..23fa942ae4bbe012ea49ebfd1108e95b607a3a4a 100644 (file)
@@ -670,6 +670,11 @@ static int malidp_runtime_pm_suspend(struct device *dev)
        struct drm_device *drm = dev_get_drvdata(dev);
        struct malidp_drm *malidp = drm_to_malidp(drm);
        struct malidp_hw_device *hwdev = malidp->dev;
+       struct clk_bulk_data clks[] = {
+               { .clk = hwdev->pclk },
+               { .clk = hwdev->aclk },
+               { .clk = hwdev->mclk },
+       };
 
        /* we can only suspend if the hardware is in config mode */
        WARN_ON(!hwdev->hw->in_config_mode(hwdev));
@@ -677,9 +682,7 @@ static int malidp_runtime_pm_suspend(struct device *dev)
        malidp_se_irq_fini(hwdev);
        malidp_de_irq_fini(hwdev);
        hwdev->pm_suspended = true;
-       clk_disable_unprepare(hwdev->mclk);
-       clk_disable_unprepare(hwdev->aclk);
-       clk_disable_unprepare(hwdev->pclk);
+       clk_bulk_disable_unprepare(ARRAY_SIZE(clks), clks);
 
        return 0;
 }
@@ -689,10 +692,17 @@ static int malidp_runtime_pm_resume(struct device *dev)
        struct drm_device *drm = dev_get_drvdata(dev);
        struct malidp_drm *malidp = drm_to_malidp(drm);
        struct malidp_hw_device *hwdev = malidp->dev;
+       struct clk_bulk_data clks[] = {
+               { .clk = hwdev->pclk },
+               { .clk = hwdev->aclk },
+               { .clk = hwdev->mclk },
+       };
+       int err;
+
+       err = clk_bulk_prepare_enable(ARRAY_SIZE(clks), clks);
+       if (err)
+               return err;
 
-       clk_prepare_enable(hwdev->pclk);
-       clk_prepare_enable(hwdev->aclk);
-       clk_prepare_enable(hwdev->mclk);
        hwdev->pm_suspended = false;
        malidp_de_irq_hw_init(hwdev);
        malidp_se_irq_hw_init(hwdev);