Properly handle power up failures during .atomic_pre_enable() by aborting the .atomic_pre_enable() to avoid accessing registers why blocks did not bring up. Otherwise this could lead to imprecise aborts when accessing MMIO while entire power domain is off.
Cc: <[email protected]> Fixes: ba3d7bf3a7ab ("drm/msm/hdmi: Convert PHY files according to new design") Signed-off-by: Krzysztof Kozlowski <[email protected]> --- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index 157f19bd90b4..db85400e574e 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -13,14 +13,16 @@ #include "msm_kms.h" #include "hdmi.h" -static void msm_hdmi_power_on(struct drm_bridge *bridge) +static int msm_hdmi_power_on(struct drm_bridge *bridge) { struct drm_device *dev = bridge->dev; struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; int ret; - pm_runtime_resume_and_get(&hdmi->pdev->dev); + ret = pm_runtime_resume_and_get(&hdmi->pdev->dev); + if (ret) + return ret; if (hdmi->extp_clk) { DBG("pixclock: %lu", hdmi->pixclock); @@ -29,9 +31,14 @@ static void msm_hdmi_power_on(struct drm_bridge *bridge) DRM_DEV_ERROR(dev->dev, "failed to set extp clk rate: %d\n", ret); ret = clk_prepare_enable(hdmi->extp_clk); - if (ret) + if (ret) { DRM_DEV_ERROR(dev->dev, "failed to enable extp clk: %d\n", ret); + pm_runtime_put(&hdmi->pdev->dev); + return ret; + } } + + return 0; } static void power_off(struct drm_bridge *bridge) @@ -287,13 +294,18 @@ static void msm_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge, msm_hdmi_set_timings(hdmi, &crtc_state->adjusted_mode); - mutex_lock(&hdmi->state_mutex); - if (!hdmi->power_on) { - msm_hdmi_phy_resource_enable(phy); - msm_hdmi_power_on(bridge); - hdmi->power_on = true; + scoped_guard(mutex, &hdmi->state_mutex) { + if (!hdmi->power_on) { + if (msm_hdmi_phy_resource_enable(phy)) + return; + + if (msm_hdmi_power_on(bridge)) { + msm_hdmi_phy_resource_disable(phy); + return; + } + hdmi->power_on = true; + } } - mutex_unlock(&hdmi->state_mutex); if (connector->display_info.is_hdmi) msm_hdmi_audio_update(hdmi); -- 2.53.0
