[PATCH v2 06/20] drm/msm/dp: Keep runtime PM calls outside the connection lock
From: Xilin Wu
Date: Thu Oct 08 2026 - 23:20:52 EST
Runtime suspend disables the display IRQ synchronously. Calling it while
holding plugged_lock can wait for an HPD IRQ thread that needs the same
lock. Acquiring a runtime PM reference under that lock can also wait for
an in-progress suspend with the same dependency.
Acquire runtime PM references before taking plugged_lock in plug and
detect handling, and release them after unlocking in unplug and detect
handling. Keep connection state and PHY operations protected while the
runtime PM reference holds the controller active.
This prepares for serializing stream operations with HPD processing
without extending the connection lock over synchronous runtime PM calls.
Assisted-by: LLM
Signed-off-by: Xilin Wu <sophon@xxxxxxxxx>
---
drivers/gpu/drm/msm/dp/dp_display.c | 30 ++++++++++++++++++++----------
1 file changed, 20 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 3ca039ff57b8..32a2ac89d8ed 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -409,14 +409,14 @@ static int msm_dp_hpd_plug_handle(struct msm_dp_display_private *dp)
dp->msm_dp_display.connector_type,
dp->link->sink_count);
- guard(mutex)(&dp->plugged_lock);
-
ret = pm_runtime_resume_and_get(&pdev->dev);
if (ret) {
DRM_ERROR("failed to pm_runtime_resume\n");
return ret;
}
+ mutex_lock(&dp->plugged_lock);
+
msm_dp_aux_enable_xfers(dp->aux, true);
msm_dp_display_host_phy_init(dp);
@@ -428,6 +428,7 @@ static int msm_dp_hpd_plug_handle(struct msm_dp_display_private *dp)
dp->link->sink_count);
dp->plugged = true;
+ mutex_unlock(&dp->plugged_lock);
return ret;
};
@@ -450,7 +451,7 @@ static int msm_dp_hpd_unplug_handle(struct msm_dp_display_private *dp)
{
struct platform_device *pdev = dp->msm_dp_display.pdev;
- guard(mutex)(&dp->plugged_lock);
+ mutex_lock(&dp->plugged_lock);
dp->panel->video_test = false;
@@ -460,8 +461,10 @@ static int msm_dp_hpd_unplug_handle(struct msm_dp_display_private *dp)
dp->msm_dp_display.connector_type,
dp->link->sink_count);
- if (!dp->plugged)
+ if (!dp->plugged) {
+ mutex_unlock(&dp->plugged_lock);
return 0;
+ }
/* Don't forget modes for eDP */
if (!dp->msm_dp_display.is_edp)
@@ -488,10 +491,10 @@ static int msm_dp_hpd_unplug_handle(struct msm_dp_display_private *dp)
dp->msm_dp_display.connector_type,
dp->link->sink_count);
- if (dp->plugged) {
- pm_runtime_put_sync(&pdev->dev);
- dp->plugged = false;
- }
+ dp->plugged = false;
+ mutex_unlock(&dp->plugged_lock);
+
+ pm_runtime_put_sync(&pdev->dev);
return 0;
}
@@ -899,19 +902,22 @@ enum drm_connector_status msm_dp_bridge_detect(struct drm_bridge *bridge,
u8 dpcd[DP_RECEIVER_CAP_SIZE];
struct drm_dp_desc desc;
bool phy_deinit;
+ bool put;
int ret;
dp = to_dp_bridge(bridge)->msm_dp_display;
priv = container_of(dp, struct msm_dp_display_private, msm_dp_display);
- guard(mutex)(&priv->plugged_lock);
ret = pm_runtime_resume_and_get(&dp->pdev->dev);
if (ret) {
DRM_ERROR("failed to pm_runtime_resume\n");
return status;
}
+ mutex_lock(&priv->plugged_lock);
+ put = false;
+
phy_deinit = msm_dp_display_host_phy_init(priv);
msm_dp_aux_enable_xfers(priv->aux, true);
@@ -961,8 +967,12 @@ enum drm_connector_status msm_dp_bridge_detect(struct drm_bridge *bridge,
msm_dp_display_host_phy_exit(priv);
}
- pm_runtime_put_sync(&dp->pdev->dev);
+ put = true;
}
+ mutex_unlock(&priv->plugged_lock);
+
+ if (put)
+ pm_runtime_put_sync(&dp->pdev->dev);
return status;
}
--
2.56.0