cdns_dsi_bridge_atomic_pre_enable() uses pm_runtime_get_sync() to resume
the DSI controller.  The helper increments the runtime PM usage count
even if the resume fails.

The corresponding post-disable callback unconditionally accesses the
controller registers, releases the PHY, and drops the runtime PM
reference.  However, the DRM bridge pre-enable callback returns void, so
a failed resume does not prevent the later post-disable callback from
running.

Use pm_runtime_resume_and_get() to avoid retaining a usage count on
failure.  Track successful runtime PM acquisition and skip post-disable
cleanup if pre-enable failed.

Also move the bridge state validation before runtime PM acquisition.

This change was prepared with assistance from DeepSeek-V4.1-Flash and
GPT-6.1-Sol.

Fixes: e19233955d9e ("drm/bridge: Add Cadence DSI driver")
Signed-off-by: Wentao Liang <[email protected]>

---
Changes in v2:
 - Sorry for the very late reply, and thanks for the review.
 - Use pm_runtime_resume_and_get() as suggested by Laurent.
 - Track successful runtime PM acquisition.
 - Skip post-disable cleanup after a failed pre-enable.
 - Validate the bridge state before acquiring the PM reference.
---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 12 +++++++++---
 drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h |  1 +
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 1e28ea579b06..da27f5611bb7 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -613,6 +613,9 @@ static void cdns_dsi_bridge_atomic_post_disable(struct 
drm_bridge *bridge,
         * disable their streams.
         */
 
+       if (!dsi->bridge_pm_active)
+               return;
+
        val = readl(dsi->regs + MCTL_MAIN_DATA_CTL);
        val &= ~(IF_VID_SELECT_MASK | IF_VID_MODE | VID_EN | HOST_EOT_GEN |
                 DISP_EOT_GEN);
@@ -630,6 +633,7 @@ static void cdns_dsi_bridge_atomic_post_disable(struct 
drm_bridge *bridge,
        phy_exit(dsi->dphy);
 
        pm_runtime_put(dsi->base.dev);
+       dsi->bridge_pm_active = false;
 }
 
 static void cdns_dsi_hs_init(struct cdns_dsi *dsi)
@@ -734,13 +738,15 @@ static void cdns_dsi_bridge_atomic_pre_enable(struct 
drm_bridge *bridge,
         * enable their streams.
         */
 
-       if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
-               return;
-
        new_bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
        if (WARN_ON(!new_bridge_state))
                return;
 
+       if (WARN_ON(pm_runtime_resume_and_get(dsi->base.dev) < 0))
+               return;
+
+       dsi->bridge_pm_active = true;
+
        dsi_state = to_cdns_dsi_bridge_state(new_bridge_state);
        dsi_cfg = dsi_state->dsi_cfg;
 
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h 
b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h
index 5db5dbbbcaad..6ed6e1bb8573 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h
@@ -76,6 +76,7 @@ struct cdns_dsi {
        struct clk *dsi_sys_clk;
        bool link_initialized;
        bool phy_initialized;
+       bool bridge_pm_active;
        struct phy *dphy;
 };
 

Reply via email to