When dpu_kms_hw_init() fails it calls _dpu_kms_hw_destroy(), the teardown of a fully initialised KMS, whatever step it failed at.
Undo only the steps which have completed, in the reverse order, as the kernel convention wants. The hw_mdp, hw_vbif and hw_intr blocks are allocated with drmm and go away with the DRM device, while dpu_kms stays around for the next bind attempt, so clear the pointers to them as _dpu_kms_hw_destroy() did. Otherwise dpu_runtime_resume() of the next bind attempt passes the stale hw_vbif to dpu_vbif_init_memtypes() before dpu_kms_hw_init() sets it. Assisted-by: LLM Signed-off-by: Dmitry Baryshkov <[email protected]> --- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 934ba47b2dae..3546efacba3c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1161,7 +1161,7 @@ static int dpu_kms_hw_init(struct dpu_kms *dpu_kms) rc = pm_runtime_resume_and_get(&dpu_kms->pdev->dev); if (rc < 0) - goto error; + goto err_global_obj_fini; core_rev = readl_relaxed(dpu_kms->mmio + 0x0); @@ -1188,19 +1188,19 @@ static int dpu_kms_hw_init(struct dpu_kms *dpu_kms) if (IS_ERR(dpu_kms->mdss)) { rc = PTR_ERR(dpu_kms->mdss); DPU_ERROR("failed to get UBWC config data: %d\n", rc); - goto err_pm_put; + goto err_mmu_destroy; } if (!dpu_kms->mdss) { rc = -EINVAL; DPU_ERROR("NULL MDSS data\n"); - goto err_pm_put; + goto err_mmu_destroy; } rc = dpu_rm_init(dev, &dpu_kms->rm, dpu_kms->catalog, dpu_kms->mdss, dpu_kms->mmio); if (rc) { DPU_ERROR("rm init failed: %d\n", rc); - goto err_pm_put; + goto err_mmu_destroy; } dpu_kms->hw_mdp = dpu_hw_mdptop_init(dev, @@ -1210,8 +1210,7 @@ static int dpu_kms_hw_init(struct dpu_kms *dpu_kms) if (IS_ERR(dpu_kms->hw_mdp)) { rc = PTR_ERR(dpu_kms->hw_mdp); DPU_ERROR("failed to get hw_mdp: %d\n", rc); - dpu_kms->hw_mdp = NULL; - goto err_pm_put; + goto err_mmu_destroy; } struct dpu_hw_vbif *hw; @@ -1221,7 +1220,7 @@ static int dpu_kms_hw_init(struct dpu_kms *dpu_kms) if (IS_ERR(hw)) { rc = PTR_ERR(hw); DPU_ERROR("failed to init vbif: %d\n", rc); - goto err_pm_put; + goto err_mmu_destroy; } dpu_kms->hw_vbif = hw; @@ -1236,7 +1235,7 @@ static int dpu_kms_hw_init(struct dpu_kms *dpu_kms) rc = dpu_core_perf_init(&dpu_kms->perf, dpu_kms->catalog->perf, max_core_clk_rate); if (rc) { DPU_ERROR("failed to init perf %d\n", rc); - goto err_pm_put; + goto err_mmu_destroy; } /* @@ -1253,8 +1252,7 @@ static int dpu_kms_hw_init(struct dpu_kms *dpu_kms) if (IS_ERR(dpu_kms->hw_intr)) { rc = PTR_ERR(dpu_kms->hw_intr); DPU_ERROR("hw_intr init failed: %d\n", rc); - dpu_kms->hw_intr = NULL; - goto err_pm_put; + goto err_mmu_destroy; } dev->mode_config.min_width = 0; @@ -1274,7 +1272,7 @@ static int dpu_kms_hw_init(struct dpu_kms *dpu_kms) rc = _dpu_kms_drm_obj_init(dpu_kms); if (rc) { DPU_ERROR("modeset init failed: %d\n", rc); - goto err_pm_put; + goto err_self_refresh_cleanup; } dpu_vbif_init_memtypes(dpu_kms); @@ -1283,10 +1281,17 @@ static int dpu_kms_hw_init(struct dpu_kms *dpu_kms) return 0; +err_self_refresh_cleanup: + dpu_kms_self_refresh_cleanup(dpu_kms); +err_mmu_destroy: + dpu_kms->hw_intr = NULL; + dpu_kms->hw_vbif = NULL; + dpu_kms->hw_mdp = NULL; + _dpu_kms_mmu_destroy(dpu_kms); err_pm_put: pm_runtime_put_sync(&dpu_kms->pdev->dev); -error: - _dpu_kms_hw_destroy(dpu_kms); +err_global_obj_fini: + dpu_kms_global_obj_fini(dpu_kms); return rc; } -- 2.47.3
