drm/i915: Ensure the HW is powered when accessing the CRC HW block

The assumption when adding the intel_display_power_is_enabled() checks
was that if it returns success the power can't be turned off afterwards
during the HW access, which is guaranteed by modeset locks. This isn't
always true, so make sure we hold a dedicated reference for the time of
the access.

While at it also add the missing reference around the HW access in
i915_interrupt_info().

v2:
- update the commit message mentioning that this also fixes the
  HW access in the interrupt info debugfs entry (Daniel)

Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1455296121-4742-9-git-send-email-imre.deak@intel.com
This commit is contained in:
Imre Deak 2016-02-12 18:55:17 +02:00
parent e27daab497
commit e129649b7a

View File

@ -825,8 +825,11 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
}
for_each_pipe(dev_priv, pipe) {
if (!intel_display_power_is_enabled(dev_priv,
POWER_DOMAIN_PIPE(pipe))) {
enum intel_display_power_domain power_domain;
power_domain = POWER_DOMAIN_PIPE(pipe);
if (!intel_display_power_get_if_enabled(dev_priv,
power_domain)) {
seq_printf(m, "Pipe %c power disabled\n",
pipe_name(pipe));
continue;
@ -840,6 +843,8 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
seq_printf(m, "Pipe %c IER:\t%08x\n",
pipe_name(pipe),
I915_READ(GEN8_DE_PIPE_IER(pipe)));
intel_display_power_put(dev_priv, power_domain);
}
seq_printf(m, "Display Engine port interrupt mask:\t%08x\n",
@ -4004,6 +4009,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
struct intel_crtc *crtc = to_intel_crtc(intel_get_crtc_for_pipe(dev,
pipe));
enum intel_display_power_domain power_domain;
u32 val = 0; /* shut up gcc */
int ret;
@ -4014,7 +4020,8 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
if (pipe_crc->source && source)
return -EINVAL;
if (!intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) {
power_domain = POWER_DOMAIN_PIPE(pipe);
if (!intel_display_power_get_if_enabled(dev_priv, power_domain)) {
DRM_DEBUG_KMS("Trying to capture CRC while pipe is off\n");
return -EIO;
}
@ -4031,7 +4038,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
ret = ivb_pipe_crc_ctl_reg(dev, pipe, &source, &val);
if (ret != 0)
return ret;
goto out;
/* none -> real source transition */
if (source) {
@ -4043,8 +4050,10 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
entries = kcalloc(INTEL_PIPE_CRC_ENTRIES_NR,
sizeof(pipe_crc->entries[0]),
GFP_KERNEL);
if (!entries)
return -ENOMEM;
if (!entries) {
ret = -ENOMEM;
goto out;
}
/*
* When IPS gets enabled, the pipe CRC changes. Since IPS gets
@ -4100,7 +4109,12 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
hsw_enable_ips(crtc);
}
return 0;
ret = 0;
out:
intel_display_power_put(dev_priv, power_domain);
return ret;
}
/*