aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorImre Deak <imre.deak@intel.com>2014-08-18 07:42:42 -0400
committerJani Nikula <jani.nikula@intel.com>2014-08-18 09:15:57 -0400
commit1c767b339b3938b19076ffdc9d70aa1e4235a45b (patch)
tree1e3962f93c558ef034dec857e590f2a2e44ec37a
parent1add143caf593cfc7514f1c83470fba0664ae0a3 (diff)
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>
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index ee3942f0b068..a520188e6d97 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -4037,15 +4037,21 @@ bool
4037intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) 4037intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
4038{ 4038{
4039 struct intel_dp *intel_dp = &intel_dig_port->dp; 4039 struct intel_dp *intel_dp = &intel_dig_port->dp;
4040 struct intel_encoder *intel_encoder = &intel_dig_port->base;
4040 struct drm_device *dev = intel_dig_port->base.base.dev; 4041 struct drm_device *dev = intel_dig_port->base.base.dev;
4041 struct drm_i915_private *dev_priv = dev->dev_private; 4042 struct drm_i915_private *dev_priv = dev->dev_private;
4042 int ret; 4043 enum intel_display_power_domain power_domain;
4044 bool ret = true;
4045
4043 if (intel_dig_port->base.type != INTEL_OUTPUT_EDP) 4046 if (intel_dig_port->base.type != INTEL_OUTPUT_EDP)
4044 intel_dig_port->base.type = INTEL_OUTPUT_DISPLAYPORT; 4047 intel_dig_port->base.type = INTEL_OUTPUT_DISPLAYPORT;
4045 4048
4046 DRM_DEBUG_KMS("got hpd irq on port %d - %s\n", intel_dig_port->port, 4049 DRM_DEBUG_KMS("got hpd irq on port %d - %s\n", intel_dig_port->port,
4047 long_hpd ? "long" : "short"); 4050 long_hpd ? "long" : "short");
4048 4051
4052 power_domain = intel_display_port_power_domain(intel_encoder);
4053 intel_display_power_get(dev_priv, power_domain);
4054
4049 if (long_hpd) { 4055 if (long_hpd) {
4050 if (!ibx_digital_port_connected(dev_priv, intel_dig_port)) 4056 if (!ibx_digital_port_connected(dev_priv, intel_dig_port))
4051 goto mst_fail; 4057 goto mst_fail;
@@ -4061,8 +4067,7 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
4061 4067
4062 } else { 4068 } else {
4063 if (intel_dp->is_mst) { 4069 if (intel_dp->is_mst) {
4064 ret = intel_dp_check_mst_status(intel_dp); 4070 if (intel_dp_check_mst_status(intel_dp) == -EINVAL)
4065 if (ret == -EINVAL)
4066 goto mst_fail; 4071 goto mst_fail;
4067 } 4072 }
4068 4073
@@ -4076,7 +4081,8 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
4076 drm_modeset_unlock(&dev->mode_config.connection_mutex); 4081 drm_modeset_unlock(&dev->mode_config.connection_mutex);
4077 } 4082 }
4078 } 4083 }
4079 return false; 4084 ret = false;
4085 goto put_power;
4080mst_fail: 4086mst_fail:
4081 /* if we were in MST mode, and device is not there get out of MST mode */ 4087 /* if we were in MST mode, and device is not there get out of MST mode */
4082 if (intel_dp->is_mst) { 4088 if (intel_dp->is_mst) {
@@ -4084,7 +4090,10 @@ mst_fail:
4084 intel_dp->is_mst = false; 4090 intel_dp->is_mst = false;
4085 drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst); 4091 drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
4086 } 4092 }
4087 return true; 4093put_power:
4094 intel_display_power_put(dev_priv, power_domain);
4095
4096 return ret;
4088} 4097}
4089 4098
4090/* Return which DP Port should be selected for Transcoder DP control */ 4099/* Return which DP Port should be selected for Transcoder DP control */