[PATCH] drm/i915: Don't deref pipe->cpu_transcoder in the hangcheck code

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>

Backporting for 3.10-stable.

The patch's failure is because of the three following commits:
1. ff57f1b09
2. 12d217c79
3. edc3d8848
which are all introduced after 3.11-rc*.
I wiped out the codes belonged to the above commits from the current patch.

From: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>

commit 63b66e5ba54b15a6592be00555d762db6db739ce upstream.

If we get an error event really early in the driver setup sequence,
which gen3 is especially prone to with various display GTT faults we
Oops. So try to avoid this.

Additionally with Haswell the transcoders are a separate bank of
registers from the pipes (4 transcoders, 3 pipes). In event of an
error, we want to be sure we have a complete and accurate picture of
the machine state, so record all the transcoders in addition to all
the active pipes.

This regression has been introduced in

commit 702e7a56af3780d8b3a717f698209bef44187bb0
Author: Paulo Zanoni <paulo.r.zanoni@xxxxxxxxx>
Date:   Tue Oct 23 18:29:59 2012 -0200

    drm/i915: convert PIPECONF to use transcoder instead of pipe

Based on the patch "drm/i915: Dump all transcoder registers on error"
from Chris Wilson:

v2: Rebase so that we don't try to be clever and try to figure out the
cpu transcoder from hw state. That exercise should be done when we
analyze the error state offline.

The actual bugfix is to not call intel_pipe_to_cpu_transcoder in the
error state capture code in case the pipes aren't fully set up yet.

v3: Simplifiy the err->num_transcoders computation a bit. While at it
make the error capture stuff save on systems without a display block.

v4: Fix fail, spotted by Jani.

v5: Completely new commit message, cc: stable.

Cc: Paulo Zanoni <paulo.r.zanoni@xxxxxxxxx>
Cc: Damien Lespiau <damien.lespiau@xxxxxxxxx>
Cc: Jani Nikula <jani.nikula@xxxxxxxxx>
Cc: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=60021
Cc: stable@xxxxxxxxxxxxxxx
Tested-by: Dustin King <daking@xxxxxxxxxxxxxxxxxxxx>
Reviewed-by: Jani Nikula <jani.nikula@xxxxxxxxx>
Reviewed-by: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>
Signed-off-by: Daniel Vetter <daniel.vetter@xxxxxxxx>
Signed-off-by: Zhouping Liu <zliu@xxxxxxxxxx>
---
 drivers/gpu/drm/i915/intel_display.c | 82 +++++++++++++++++++++++++-----------
 1 file changed, 57 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index eea5982..ede352f 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -9541,6 +9541,8 @@ int intel_modeset_vga_set_state(struct drm_device *dev, bool state)
 #include <linux/seq_file.h>
 
 struct intel_display_error_state {
+	int num_transcoders;
+
 	struct intel_cursor_error_state {
 		u32 control;
 		u32 position;
@@ -9549,15 +9551,7 @@ struct intel_display_error_state {
 	} cursor[I915_MAX_PIPES];
 
 	struct intel_pipe_error_state {
-		u32 conf;
 		u32 source;
-
-		u32 htotal;
-		u32 hblank;
-		u32 hsync;
-		u32 vtotal;
-		u32 vblank;
-		u32 vsync;
 	} pipe[I915_MAX_PIPES];
 
 	struct intel_plane_error_state {
@@ -9569,6 +9563,19 @@ struct intel_display_error_state {
 		u32 surface;
 		u32 tile_offset;
 	} plane[I915_MAX_PIPES];
+
+	struct intel_transcoder_error_state {
+		enum transcoder cpu_transcoder;
+
+		u32 conf;
+
+		u32 htotal;
+		u32 hblank;
+		u32 hsync;
+		u32 vtotal;
+		u32 vblank;
+		u32 vsync;
+	} transcoder[4];
 };
 
 struct intel_display_error_state *
@@ -9576,16 +9583,22 @@ 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;
+	int transcoders[] = {
+		TRANSCODER_A,
+		TRANSCODER_B,
+		TRANSCODER_C,
+		TRANSCODER_EDP,
+	};
 	int i;
 
+	if (INTEL_INFO(dev)->num_pipes == 0)
+		return NULL;
+
 	error = kmalloc(sizeof(*error), GFP_ATOMIC);
 	if (error == NULL)
 		return NULL;
 
 	for_each_pipe(i) {
-		cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, i);
-
 		if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) {
 			error->cursor[i].control = I915_READ(CURCNTR(i));
 			error->cursor[i].position = I915_READ(CURPOS(i));
@@ -9609,14 +9622,25 @@ 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));
+	}
+
+	error->num_transcoders = INTEL_INFO(dev)->num_pipes;
+	if (HAS_DDI(dev_priv->dev))
+		error->num_transcoders++; /* Account for eDP. */
+
+	for (i = 0; i < error->num_transcoders; i++) {
+		enum transcoder cpu_transcoder = transcoders[i];
+
+		error->transcoder[i].cpu_transcoder = cpu_transcoder;
+
+		error->transcoder[i].conf = I915_READ(PIPECONF(cpu_transcoder));
+		error->transcoder[i].htotal = I915_READ(HTOTAL(cpu_transcoder));
+		error->transcoder[i].hblank = I915_READ(HBLANK(cpu_transcoder));
+		error->transcoder[i].hsync = I915_READ(HSYNC(cpu_transcoder));
+		error->transcoder[i].vtotal = I915_READ(VTOTAL(cpu_transcoder));
+		error->transcoder[i].vblank = I915_READ(VBLANK(cpu_transcoder));
+		error->transcoder[i].vsync = I915_READ(VSYNC(cpu_transcoder));
 	}
 
 	return error;
@@ -9629,17 +9653,13 @@ intel_display_print_error_state(struct seq_file *m,
 {
 	int i;
 
+	if (!error)
+		return;
+
 	seq_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes);
 	for_each_pipe(i) {
 		seq_printf(m, "Pipe [%d]:\n", i);
-		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);
-		seq_printf(m, "  HBLANK: %08x\n", error->pipe[i].hblank);
-		seq_printf(m, "  HSYNC: %08x\n", error->pipe[i].hsync);
-		seq_printf(m, "  VTOTAL: %08x\n", error->pipe[i].vtotal);
-		seq_printf(m, "  VBLANK: %08x\n", error->pipe[i].vblank);
-		seq_printf(m, "  VSYNC: %08x\n", error->pipe[i].vsync);
 
 		seq_printf(m, "Plane [%d]:\n", i);
 		seq_printf(m, "  CNTR: %08x\n", error->plane[i].control);
@@ -9660,5 +9680,17 @@ intel_display_print_error_state(struct seq_file *m,
 		seq_printf(m, "  POS: %08x\n", error->cursor[i].position);
 		seq_printf(m, "  BASE: %08x\n", error->cursor[i].base);
 	}
+
+	for (i = 0; i < error->num_transcoders; i++) {
+		seq_printf(m, "  CPU transcoder: %c\n",
+			   transcoder_name(error->transcoder[i].cpu_transcoder));
+		seq_printf(m, "  CONF: %08x\n", error->transcoder[i].conf);
+		seq_printf(m, "  HTOTAL: %08x\n", error->transcoder[i].htotal);
+		seq_printf(m, "  HBLANK: %08x\n", error->transcoder[i].hblank);
+		seq_printf(m, "  HSYNC: %08x\n", error->transcoder[i].hsync);
+		seq_printf(m, "  VTOTAL: %08x\n", error->transcoder[i].vtotal);
+		seq_printf(m, "  VBLANK: %08x\n", error->transcoder[i].vblank);
+		seq_printf(m, "  VSYNC: %08x\n", error->transcoder[i].vsync);
+	}
 }
 #endif
-- 
1.7.11.7

--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]