Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ef3d427 authored by Chris Wilson's avatar Chris Wilson Committed by Eric Anholt
Browse files

drm/i915: Capture the overlay status upon a GPU hang.



v2: Add the interrupt status and address.

Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: default avatarEric Anholt <eric@anholt.net>
parent dbd7ac96
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -467,6 +467,9 @@ static int i915_error_state(struct seq_file *m, void *unused)
		}
	}

	if (error->overlay)
		intel_overlay_print_error_state(m, error->overlay);

out:
	spin_unlock_irqrestore(&dev_priv->error_lock, flags);

+8 −2
Original line number Diff line number Diff line
@@ -113,6 +113,9 @@ struct intel_opregion {
	int enabled;
};

struct intel_overlay;
struct intel_overlay_error_state;

struct drm_i915_master_private {
	drm_local_map_t *sarea;
	struct _drm_i915_sarea *sarea_priv;
@@ -166,6 +169,7 @@ struct drm_i915_error_state {
		u32 purgeable:1;
	} *active_bo;
	u32 active_bo_count;
	struct intel_overlay_error_state *overlay;
};

struct drm_i915_display_funcs {
@@ -186,8 +190,6 @@ struct drm_i915_display_funcs {
	/* clock gating init */
};

struct intel_overlay;

struct intel_device_info {
	u8 is_mobile : 1;
	u8 is_i8xx : 1;
@@ -1069,6 +1071,10 @@ extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
extern void intel_detect_pch (struct drm_device *dev);
extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);

/* overlay */
extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error);

/**
 * Lock test for when it's just for synchronization of ring access.
 *
+3 −0
Original line number Diff line number Diff line
@@ -489,6 +489,7 @@ i915_error_state_free(struct drm_device *dev,
	i915_error_object_free(error->batchbuffer[1]);
	i915_error_object_free(error->ringbuffer);
	kfree(error->active_bo);
	kfree(error->overlay);
	kfree(error);
}

@@ -667,6 +668,8 @@ static void i915_capture_error_state(struct drm_device *dev)

	do_gettimeofday(&error->time);

	error->overlay = intel_overlay_capture_error_state(dev);

	spin_lock_irqsave(&dev_priv->error_lock, flags);
	if (dev_priv->first_error == NULL) {
		dev_priv->first_error = error;
+96 −0
Original line number Diff line number Diff line
@@ -1416,3 +1416,99 @@ void intel_cleanup_overlay(struct drm_device *dev)
		kfree(dev_priv->overlay);
	}
}

struct intel_overlay_error_state {
	struct overlay_registers regs;
	unsigned long base;
	u32 dovsta;
	u32 isr;
};

struct intel_overlay_error_state *
intel_overlay_capture_error_state(struct drm_device *dev)
{
        drm_i915_private_t *dev_priv = dev->dev_private;
	struct intel_overlay *overlay = dev_priv->overlay;
	struct intel_overlay_error_state *error;
	struct overlay_registers __iomem *regs;

	if (!overlay || !overlay->active)
		return NULL;

	error = kmalloc(sizeof(*error), GFP_ATOMIC);
	if (error == NULL)
		return NULL;

	error->dovsta = I915_READ(DOVSTA);
	error->isr = I915_READ(ISR);
	if (OVERLAY_NONPHYSICAL(overlay->dev))
		error->base = (long) overlay->reg_bo->gtt_offset;
	else
		error->base = (long) overlay->reg_bo->phys_obj->handle->vaddr;

	regs = intel_overlay_map_regs_atomic(overlay);
	if (!regs)
		goto err;

	memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers));
	intel_overlay_unmap_regs_atomic(overlay);

	return error;

err:
	kfree(error);
	return NULL;
}

void
intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error)
{
	seq_printf(m, "Overlay, status: 0x%08x, interrupt: 0x%08x\n",
		   error->dovsta, error->isr);
	seq_printf(m, "  Register file at 0x%08lx:\n",
		   error->base);

#define P(x) seq_printf(m, "    " #x ":	0x%08x\n", error->regs.x)
	P(OBUF_0Y);
	P(OBUF_1Y);
	P(OBUF_0U);
	P(OBUF_0V);
	P(OBUF_1U);
	P(OBUF_1V);
	P(OSTRIDE);
	P(YRGB_VPH);
	P(UV_VPH);
	P(HORZ_PH);
	P(INIT_PHS);
	P(DWINPOS);
	P(DWINSZ);
	P(SWIDTH);
	P(SWIDTHSW);
	P(SHEIGHT);
	P(YRGBSCALE);
	P(UVSCALE);
	P(OCLRC0);
	P(OCLRC1);
	P(DCLRKV);
	P(DCLRKM);
	P(SCLRKVH);
	P(SCLRKVL);
	P(SCLRKEN);
	P(OCONFIG);
	P(OCMD);
	P(OSTART_0Y);
	P(OSTART_1Y);
	P(OSTART_0U);
	P(OSTART_0V);
	P(OSTART_1U);
	P(OSTART_1V);
	P(OTILEOFF_0Y);
	P(OTILEOFF_1Y);
	P(OTILEOFF_0U);
	P(OTILEOFF_0V);
	P(OTILEOFF_1U);
	P(OTILEOFF_1V);
	P(FASTHSCALE);
	P(UVSCALEV);
#undef P
}