[PATCH 04/11] drm/msm: let the kms drivers clean up a failed kms_init()

From: Dmitry Baryshkov

Date: Fri Oct 02 2026 - 20:28:26 EST


A failed priv->kms_init() or ->hw_init() is cleaned up by the ->destroy()
callback, which makes ->destroy() responsible for tearing down a KMS in
any state between "not initialised at all" and "fully initialised". The
kernel convention is the opposite: a function which fails undoes its own
steps, and the teardown only ever sees a fully set up object.

Let the kms drivers switch to that convention one at a time: skip
->destroy() after a failed kms_init() of a driver which sets
init_unwinds, and let the drivers fold their hardware setup into
kms_init() and drop ->hw_init(). Set up the mode config before calling
kms_init(), so that it is already in place for the hardware setup.

The flag and the optional ->hw_init() go away once all the drivers have
been converted.

Assisted-by: LLM
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@xxxxxxxxxxxxxxxx>
---
drivers/gpu/drm/msm/msm_kms.c | 23 ++++++++++++++---------
drivers/gpu/drm/msm/msm_kms.h | 3 +++
2 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_kms.c b/drivers/gpu/drm/msm/msm_kms.c
index f3e39c3907a9..f65774b04c6f 100644
--- a/drivers/gpu/drm/msm/msm_kms.c
+++ b/drivers/gpu/drm/msm/msm_kms.c
@@ -285,12 +285,6 @@ int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv)
return ret;
}

- ret = priv->kms_init(ddev);
- if (ret) {
- DRM_DEV_ERROR(dev, "failed to load kms\n");
- goto err_destroy_kms;
- }
-
/* Enable normalization of plane zpos */
ddev->mode_config.normalize_zpos = true;

@@ -298,12 +292,22 @@ int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv)
ddev->mode_config.helper_private = &mode_config_helper_funcs;

kms->dev = ddev;
- ret = kms->funcs->hw_init(kms);
+ ret = priv->kms_init(ddev);
if (ret) {
- DRM_DEV_ERROR(dev, "kms hw init failed: %d\n", ret);
+ DRM_DEV_ERROR(dev, "failed to load kms\n");
+ if (kms->init_unwinds)
+ goto err_destroy_snapshot;
goto err_destroy_kms;
}

+ if (kms->funcs->hw_init) {
+ ret = kms->funcs->hw_init(kms);
+ if (ret) {
+ DRM_DEV_ERROR(dev, "kms hw init failed: %d\n", ret);
+ goto err_destroy_kms;
+ }
+ }
+
drm_helper_move_panel_connectors_to_head(ddev);

drm_for_each_crtc(crtc, ddev) {
@@ -344,9 +348,10 @@ int msm_drm_kms_init(struct device *dev, const struct drm_driver *drv)
err_destroy_event_threads:
msm_drm_kms_destroy_event_threads(kms);
err_destroy_kms:
- msm_disp_snapshot_destroy(ddev);
if (kms->funcs)
kms->funcs->destroy(kms);
+err_destroy_snapshot:
+ msm_disp_snapshot_destroy(ddev);

return ret;
}
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index ee98393b9855..2f097e23e2e9 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -149,6 +149,9 @@ struct msm_kms {
int irq;
bool irq_requested;

+ /* set by the kms drivers whose kms_init() undoes its own failures */
+ bool init_unwinds;
+
/* rate limit the snapshot capture to once per attach */
atomic_t fault_snapshot_capture;


--
2.47.3