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
