mirror of https://gitee.com/openkylin/linux.git
drm/i915: take display port power domain in DP HPD handler
Ville noticed that we can call ibx_digital_port_connected() which accesses the HW without holding any power well/runtime pm reference. Fix this by holding a display port power domain reference around the whole hpd_pulse handler. Signed-off-by: Imre Deak <imre.deak@intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Dave Airlie <airlied@redhat.com> Cc: stable@vger.kernel.org (3.16+) Signed-off-by: Jani Nikula <jani.nikula@intel.com>
This commit is contained in:
parent
1add143caf
commit
1c767b339b
|
@ -4037,15 +4037,21 @@ bool
|
||||||
intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
|
intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
|
||||||
{
|
{
|
||||||
struct intel_dp *intel_dp = &intel_dig_port->dp;
|
struct intel_dp *intel_dp = &intel_dig_port->dp;
|
||||||
|
struct intel_encoder *intel_encoder = &intel_dig_port->base;
|
||||||
struct drm_device *dev = intel_dig_port->base.base.dev;
|
struct drm_device *dev = intel_dig_port->base.base.dev;
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
int ret;
|
enum intel_display_power_domain power_domain;
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
if (intel_dig_port->base.type != INTEL_OUTPUT_EDP)
|
if (intel_dig_port->base.type != INTEL_OUTPUT_EDP)
|
||||||
intel_dig_port->base.type = INTEL_OUTPUT_DISPLAYPORT;
|
intel_dig_port->base.type = INTEL_OUTPUT_DISPLAYPORT;
|
||||||
|
|
||||||
DRM_DEBUG_KMS("got hpd irq on port %d - %s\n", intel_dig_port->port,
|
DRM_DEBUG_KMS("got hpd irq on port %d - %s\n", intel_dig_port->port,
|
||||||
long_hpd ? "long" : "short");
|
long_hpd ? "long" : "short");
|
||||||
|
|
||||||
|
power_domain = intel_display_port_power_domain(intel_encoder);
|
||||||
|
intel_display_power_get(dev_priv, power_domain);
|
||||||
|
|
||||||
if (long_hpd) {
|
if (long_hpd) {
|
||||||
if (!ibx_digital_port_connected(dev_priv, intel_dig_port))
|
if (!ibx_digital_port_connected(dev_priv, intel_dig_port))
|
||||||
goto mst_fail;
|
goto mst_fail;
|
||||||
|
@ -4061,8 +4067,7 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (intel_dp->is_mst) {
|
if (intel_dp->is_mst) {
|
||||||
ret = intel_dp_check_mst_status(intel_dp);
|
if (intel_dp_check_mst_status(intel_dp) == -EINVAL)
|
||||||
if (ret == -EINVAL)
|
|
||||||
goto mst_fail;
|
goto mst_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4076,7 +4081,8 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
|
||||||
drm_modeset_unlock(&dev->mode_config.connection_mutex);
|
drm_modeset_unlock(&dev->mode_config.connection_mutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
ret = false;
|
||||||
|
goto put_power;
|
||||||
mst_fail:
|
mst_fail:
|
||||||
/* if we were in MST mode, and device is not there get out of MST mode */
|
/* if we were in MST mode, and device is not there get out of MST mode */
|
||||||
if (intel_dp->is_mst) {
|
if (intel_dp->is_mst) {
|
||||||
|
@ -4084,7 +4090,10 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
|
||||||
intel_dp->is_mst = false;
|
intel_dp->is_mst = false;
|
||||||
drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
|
drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
|
||||||
}
|
}
|
||||||
return true;
|
put_power:
|
||||||
|
intel_display_power_put(dev_priv, power_domain);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return which DP Port should be selected for Transcoder DP control */
|
/* Return which DP Port should be selected for Transcoder DP control */
|
||||||
|
|
Loading…
Reference in New Issue