When dpu_kms_hw_init() fails it calls _dpu_kms_hw_destroy() itself, and
the caller then runs the ->destroy() callback, which calls
_dpu_kms_hw_destroy() a second time. Since the global state object is
finalised there, the second call deletes its list entry again and frees
its state twice.

Fold the hardware setup into dpu_kms_init(), undo the steps of
dpu_kms_init() when it fails, and tell the caller not to run ->destroy()
after a failed init.

Fixes: 49e27d3c9cd6 ("drm/msm/dpu: finalise global state object")
Assisted-by: LLM
Signed-off-by: Dmitry Baryshkov <[email protected]>
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 29 +++++++++++++++--------------
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index da3556eb6ecc..255beb83fc94 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -55,7 +55,6 @@
 bool dpu_use_virtual_planes = true;
 module_param(dpu_use_virtual_planes, bool, 0);
 
-static int dpu_kms_hw_init(struct msm_kms *kms);
 static void _dpu_kms_mmu_destroy(struct dpu_kms *dpu_kms);
 
 #ifdef CONFIG_DEBUG_FS
@@ -1067,7 +1066,6 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state 
*disp_state, struct msm_k
 }
 
 static const struct msm_kms_funcs kms_funcs = {
-       .hw_init         = dpu_kms_hw_init,
        .irq_preinstall  = dpu_core_irq_preinstall,
        .irq_postinstall = dpu_irq_postinstall,
        .irq_uninstall   = dpu_core_irq_uninstall,
@@ -1135,21 +1133,12 @@ unsigned long dpu_kms_get_clk_rate(struct dpu_kms 
*dpu_kms, char *clock_name)
 
 #define        DPU_PERF_DEFAULT_MAX_CORE_CLK_RATE      412500000
 
-static int dpu_kms_hw_init(struct msm_kms *kms)
+static int dpu_kms_hw_init(struct dpu_kms *dpu_kms)
 {
-       struct dpu_kms *dpu_kms;
-       struct drm_device *dev;
-       int rc = -EINVAL;
+       struct drm_device *dev = dpu_kms->dev;
        unsigned long max_core_clk_rate;
        u32 core_rev;
-
-       if (!kms) {
-               DPU_ERROR("invalid kms\n");
-               return rc;
-       }
-
-       dpu_kms = to_dpu_kms(kms);
-       dev = dpu_kms->dev;
+       int rc;
 
        dev->mode_config.cursor_width = 512;
        dev->mode_config.cursor_height = 512;
@@ -1301,6 +1290,8 @@ static int dpu_kms_init(struct drm_device *ddev)
        int ret = 0;
        unsigned long max_freq = ULONG_MAX;
 
+       dpu_kms->base.init_unwinds = true;
+
        opp = dev_pm_opp_find_freq_floor(dev, &max_freq);
        if (!IS_ERR(opp))
                dev_pm_opp_put(opp);
@@ -1317,7 +1308,17 @@ static int dpu_kms_init(struct drm_device *ddev)
        pm_runtime_enable(&pdev->dev);
        dpu_kms->rpm_enabled = true;
 
+       ret = dpu_kms_hw_init(dpu_kms);
+       if (ret)
+               goto err_disable_rpm;
+
        return 0;
+
+err_disable_rpm:
+       pm_runtime_disable(&pdev->dev);
+       msm_kms_destroy(&dpu_kms->base);
+
+       return ret;
 }
 
 static int dpu_kms_mmap_mdp5(struct dpu_kms *dpu_kms)

-- 
2.47.3

Reply via email to