When priv->kms_init() (mdp4_kms_init() / mdp5_kms_init()) fails partway
through, both display drivers already tear their KMS state down via
mdp4_destroy() / mdp5_kms_destroy() before returning the error. The
common error path in msm_drm_init() then runs msm_drm_uninit() ->
msm_drm_kms_uninit(), which tries to destroy the very same KMS a second
time, which causes a use-after-free crash.

Bring MDP4/MDP5 in line with the DPU driver whose dpu_kms_init() doesn't
perform error cleanup on the failure. Let the common path own the
cleanup, instead of freeing the KMS from their error paths.

The crash trace for the reference:

  __lock_acquire from lock_acquire (kernel/locking/lockdep.c:5906 
kernel/locking/lockdep.c:5863)
  lock_acquire from touch_wq_lockdep_map (kernel/workqueue.c:4094 
(discriminator 1))
  touch_wq_lockdep_map from __flush_workqueue (kernel/workqueue.c:4136)
  __flush_workqueue from msm_drm_kms_uninit (drivers/gpu/drm/msm/msm_kms.c:243 
(discriminator 33))
  msm_drm_kms_uninit from msm_drm_uninit (drivers/gpu/drm/msm/msm_drv.c:93)
  msm_drm_uninit from msm_drm_init (drivers/gpu/drm/msm/msm_drv.c:184)
  msm_drm_init from try_to_bring_up_aggregate_device 
(drivers/base/component.c:249 drivers/base/component.c:227)
  try_to_bring_up_aggregate_device from __component_add 
(drivers/base/component.c:269 drivers/base/component.c:748)
  __component_add from dsi_host_attach (drivers/gpu/drm/msm/dsi/dsi_host.c:1739)
  dsi_host_attach from mipi_dsi_attach (drivers/gpu/drm/drm_mipi_dsi.c:383)
  mipi_dsi_attach from sharp_nt_panel_probe 
(drivers/gpu/drm/panel/panel-sharp-ls043t1le01.c:247)

Fixes: 506efcba3129 ("drm/msm: carve out KMS code from msm_drv.c")
Signed-off-by: Dmitry Baryshkov <[email protected]>
---
 drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c | 22 ++++++++--------------
 drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 11 +++--------
 2 files changed, 11 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c 
b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
index 7726edb0d4ed..6ae49f94fea7 100644
--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
@@ -398,7 +398,7 @@ static int mdp4_kms_init(struct drm_device *dev)
        ret = mdp_kms_init(&mdp4_kms->base, &kms_funcs);
        if (ret) {
                DRM_DEV_ERROR(dev->dev, "failed to init kms\n");
-               goto fail;
+               return ret;
        }
 
        kms = priv->kms;
@@ -409,7 +409,7 @@ static int mdp4_kms_init(struct drm_device *dev)
                ret = regulator_enable(mdp4_kms->vdd);
                if (ret) {
                        DRM_DEV_ERROR(dev->dev, "failed to enable regulator 
vdd: %d\n", ret);
-                       goto fail;
+                       return ret;
                }
        }
 
@@ -421,7 +421,7 @@ static int mdp4_kms_init(struct drm_device *dev)
                DRM_DEV_ERROR(dev->dev, "unexpected MDP version: v%d.%d\n",
                              major, minor);
                ret = -ENXIO;
-               goto fail;
+               return ret;
        }
 
        mdp4_kms->rev = minor;
@@ -430,7 +430,7 @@ static int mdp4_kms_init(struct drm_device *dev)
                if (!mdp4_kms->lut_clk) {
                        DRM_DEV_ERROR(dev->dev, "failed to get lut_clk\n");
                        ret = -ENODEV;
-                       goto fail;
+                       return ret;
                }
                clk_set_rate(mdp4_kms->lut_clk, max_clk);
        }
@@ -452,7 +452,7 @@ static int mdp4_kms_init(struct drm_device *dev)
        vm = msm_kms_init_vm(mdp4_kms->dev, NULL);
        if (IS_ERR(vm)) {
                ret = PTR_ERR(vm);
-               goto fail;
+               return ret;
        }
 
        kms->vm = vm;
@@ -460,7 +460,7 @@ static int mdp4_kms_init(struct drm_device *dev)
        ret = modeset_init(mdp4_kms);
        if (ret) {
                DRM_DEV_ERROR(dev->dev, "modeset_init failed: %d\n", ret);
-               goto fail;
+               return ret;
        }
 
        mdp4_kms->blank_cursor_bo = msm_gem_new(dev, SZ_16K, MSM_BO_WC | 
MSM_BO_SCANOUT);
@@ -468,14 +468,14 @@ static int mdp4_kms_init(struct drm_device *dev)
                ret = PTR_ERR(mdp4_kms->blank_cursor_bo);
                DRM_DEV_ERROR(dev->dev, "could not allocate blank-cursor bo: 
%d\n", ret);
                mdp4_kms->blank_cursor_bo = NULL;
-               goto fail;
+               return ret;
        }
 
        ret = msm_gem_get_and_pin_iova(mdp4_kms->blank_cursor_bo, kms->vm,
                        &mdp4_kms->blank_cursor_iova);
        if (ret) {
                DRM_DEV_ERROR(dev->dev, "could not pin blank-cursor bo: %d\n", 
ret);
-               goto fail;
+               return ret;
        }
 
        dev->mode_config.min_width = 0;
@@ -484,12 +484,6 @@ static int mdp4_kms_init(struct drm_device *dev)
        dev->mode_config.max_height = 2048;
 
        return 0;
-
-fail:
-       if (kms)
-               mdp4_destroy(kms);
-
-       return ret;
 }
 
 static const struct dev_pm_ops mdp4_pm_ops = {
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index 0a004ab9fc85..3934cd060b27 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -517,7 +517,7 @@ static int mdp5_kms_init(struct drm_device *dev)
        ret = mdp_kms_init(&mdp5_kms->base, &kms_funcs);
        if (ret) {
                DRM_DEV_ERROR(&pdev->dev, "failed to init kms\n");
-               goto fail;
+               return ret;
        }
 
        config = mdp5_cfg_get_config(mdp5_kms->cfg);
@@ -540,7 +540,7 @@ static int mdp5_kms_init(struct drm_device *dev)
        vm = msm_kms_init_vm(mdp5_kms->dev, pdev->dev.parent);
        if (IS_ERR(vm)) {
                ret = PTR_ERR(vm);
-               goto fail;
+               return ret;
        }
 
        kms->vm = vm;
@@ -550,7 +550,7 @@ static int mdp5_kms_init(struct drm_device *dev)
        ret = modeset_init(mdp5_kms);
        if (ret) {
                DRM_DEV_ERROR(&pdev->dev, "modeset_init failed: %d\n", ret);
-               goto fail;
+               return ret;
        }
 
        dev->mode_config.min_width = 0;
@@ -562,11 +562,6 @@ static int mdp5_kms_init(struct drm_device *dev)
        dev->vblank_disable_immediate = true;
 
        return 0;
-fail:
-       if (kms)
-               mdp5_kms_destroy(kms);
-
-       return ret;
 }
 
 static void mdp5_destroy(struct mdp5_kms *mdp5_kms)

---
base-commit: b9810cd75b9fb56a3425d391cba3f608502bd474
change-id: 20260723-msm-fix-crash-8c13220d9465

Best regards,
--  
With best wishes
Dmitry

Reply via email to