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 <[email protected]>
---
 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

Reply via email to