From: Paulo Zanoni <paulo.r.zanoni at intel.com> This solves many "unclaimed register" messages when the power well is down and we get a GPU hang. Also print the power well register and each pipe's CPU transcoder on the error state to allow proper interpratation of the registers. And kzalloc the error state structure since we may not read some of the registers (to avoid the "unclaimed register" messages). Signed-off-by: Paulo Zanoni <paulo.r.zanoni at intel.com> --- drivers/gpu/drm/i915/intel_display.c | 42 ++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b319cd3..835bec2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9290,6 +9290,9 @@ int intel_modeset_vga_set_state(struct drm_device *dev, bool state) #include <linux/seq_file.h> struct intel_display_error_state { + + u32 power_well_driver; + struct intel_cursor_error_state { u32 control; u32 position; @@ -9298,6 +9301,7 @@ struct intel_display_error_state { } cursor[I915_MAX_PIPES]; struct intel_pipe_error_state { + enum transcoder cpu_transcoder; u32 conf; u32 source; @@ -9324,15 +9328,35 @@ intel_display_capture_error_state(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; struct intel_display_error_state *error; - enum transcoder cpu_transcoder; + enum transcoder transcoder; + bool power_well_is_down; int i; - error = kmalloc(sizeof(*error), GFP_ATOMIC); + error = kzalloc(sizeof(*error), GFP_ATOMIC); if (error == NULL) return NULL; + power_well_is_down = intel_power_well_is_down(dev); + + if (IS_HASWELL(dev)) + error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER); + for_each_pipe(i) { - cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, i); + transcoder = intel_pipe_to_cpu_transcoder(dev_priv, i); + error->pipe[i].cpu_transcoder = transcoder; + + if (transcoder == TRANSCODER_EDP || !power_well_is_down) { + error->pipe[i].conf = I915_READ(PIPECONF(transcoder)); + error->pipe[i].htotal = I915_READ(HTOTAL(transcoder)); + error->pipe[i].hblank = I915_READ(HBLANK(transcoder)); + error->pipe[i].hsync = I915_READ(HSYNC(transcoder)); + error->pipe[i].vtotal = I915_READ(VTOTAL(transcoder)); + error->pipe[i].vblank = I915_READ(VBLANK(transcoder)); + error->pipe[i].vsync = I915_READ(VSYNC(transcoder)); + } + + if (power_well_is_down) + continue; if (INTEL_INFO(dev)->gen <= 6) { error->cursor[i].control = I915_READ(CURCNTR(i)); @@ -9355,14 +9379,7 @@ intel_display_capture_error_state(struct drm_device *dev) error->plane[i].tile_offset = I915_READ(DSPTILEOFF(i)); } - error->pipe[i].conf = I915_READ(PIPECONF(cpu_transcoder)); error->pipe[i].source = I915_READ(PIPESRC(i)); - error->pipe[i].htotal = I915_READ(HTOTAL(cpu_transcoder)); - error->pipe[i].hblank = I915_READ(HBLANK(cpu_transcoder)); - error->pipe[i].hsync = I915_READ(HSYNC(cpu_transcoder)); - error->pipe[i].vtotal = I915_READ(VTOTAL(cpu_transcoder)); - error->pipe[i].vblank = I915_READ(VBLANK(cpu_transcoder)); - error->pipe[i].vsync = I915_READ(VSYNC(cpu_transcoder)); } return error; @@ -9377,8 +9394,13 @@ intel_display_print_error_state(struct seq_file *m, int i; seq_printf(m, "Num Pipes: %d\n", dev_priv->num_pipe); + if (IS_HASWELL(dev)) + seq_printf(m, "PWR_WELL_CTL2: %08x\n", + error->power_well_driver); for_each_pipe(i) { seq_printf(m, "Pipe [%d]:\n", i); + seq_printf(m, " CPU transcoder: %c\n", + transcoder_name(error->pipe[i].cpu_transcoder)); seq_printf(m, " CONF: %08x\n", error->pipe[i].conf); seq_printf(m, " SRC: %08x\n", error->pipe[i].source); seq_printf(m, " HTOTAL: %08x\n", error->pipe[i].htotal); -- 1.7.10.4