mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
drm/msm: don't tear down KMS twice when KMS init fails
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: 506efcba31 ("drm/msm: carve out KMS code from msm_drv.c")
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Patchwork: https://patchwork.freedesktop.org/patch/742068/
Link: https://lore.kernel.org/r/20260723-msm-fix-crash-v1-1-78fb4721c2d9@oss.qualcomm.com
This commit is contained in:
parent
8834f5494a
commit
93c125e4ea
|
|
@ -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, NULL);
|
||||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user