summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMika Kuoppala <mika.kuoppala@intel.com>2015-06-26 12:19:22 +0300
committerMika Kuoppala <mika.kuoppala@intel.com>2015-06-26 17:47:46 +0300
commit123ec8cc620c915cda4fe04dfb233c544a7872c1 (patch)
treebeff1ebcfbb77d366bfac07e99e833228aaa85da
parentfd98d79140c39f3e4234f38c535213f3e757c38f (diff)
drm/i915: Check scratch page integrity on hangcheckscratch_check
At each hangcheck interval, do a lightweight check that scratch page has the magic values intact. We check either start or end of page depending on the accumulated athcd (randomness), and then a random location. If hang is declared, we do a full check for whole page. Suggested-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Mika Kuoppala <mika.kuoppala@intel.com>
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.c51
-rw-r--r--drivers/gpu/drm/i915/i915_gem_gtt.h3
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c8
3 files changed, 54 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 5fd956e577ce..608aa8443bc4 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -587,29 +587,64 @@ static int setup_scratch(struct i915_address_space *vm)
return 0;
}
-static void check_scratch_page(struct i915_address_space *vm)
+static void check_scratch_index(const u64 *vaddr, const int i)
{
- struct i915_hw_ppgtt *ppgtt =
- container_of(vm, struct i915_hw_ppgtt, base);
- int i;
- u64 *vaddr;
+ if (vaddr[i] != SCRATCH_PAGE_MAGIC)
+ DRM_ERROR("scratch[%d] = 0x%08llx\n", i, vaddr[i]);
+}
- vaddr = kmap_px(vm->scratch_page);
+static void do_light_scratch_check(const u64 *vaddr, const u64 rnd)
+{
+ if (rnd & 0x01)
+ check_scratch_index(vaddr, 0);
+ else
+ check_scratch_index(vaddr, PAGE_SIZE - 1);
+
+ check_scratch_index(vaddr, rnd % PAGE_SIZE);
+}
+
+static void do_full_scratch_check(const u64 *vaddr)
+{
+ int i;
for (i = 0; i < PAGE_SIZE / sizeof(u64); i++) {
if (vaddr[i] == SCRATCH_PAGE_MAGIC)
continue;
- DRM_ERROR("%p scratch[%d] = 0x%08llx\n", vm, i, vaddr[i]);
+ DRM_ERROR("scratch[%d] = 0x%08llx\n", i, vaddr[i]);
break;
}
+}
+
+static void check_scratch_page(struct i915_address_space *vm, const u64 rnd)
+{
+ struct i915_hw_ppgtt *ppgtt =
+ container_of(vm, struct i915_hw_ppgtt, base);
+ u64 *vaddr;
+
+ vaddr = kmap_px(vm->scratch_page);
+
+ if (rnd)
+ do_light_scratch_check(vaddr, rnd);
+ else
+ do_full_scratch_check(vaddr);
kunmap_px(ppgtt, vaddr);
}
+void i915_check_scratch_page(struct drm_i915_private *dev_priv, const u64 rnd)
+{
+ struct i915_address_space *vm = &dev_priv->gtt.base;
+
+ if (!vm->scratch_page)
+ return;
+
+ check_scratch_page(vm, rnd);
+}
+
static void cleanup_scratch_ggtt(struct i915_address_space *vm)
{
- check_scratch_page(vm);
+ check_scratch_page(vm, 0);
free_scratch_page(vm);
if (INTEL_INFO(vm->dev)->gen < 6)
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h
index e1cfa292f9ad..3c04ad79d606 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -536,4 +536,7 @@ size_t
i915_ggtt_view_size(struct drm_i915_gem_object *obj,
const struct i915_ggtt_view *view);
+struct drm_i915_private;
+void i915_check_scratch_page(struct drm_i915_private *dev_priv, const u64 rnd);
+
#endif
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index a6fbe6443d63..d343ef7e246d 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2344,6 +2344,8 @@ void i915_handle_error(struct drm_device *dev, bool wedged,
va_list args;
char error_msg[80];
+ i915_check_scratch_page(dev_priv, 0);
+
va_start(args, fmt);
vscnprintf(error_msg, sizeof(error_msg), fmt, args);
va_end(args);
@@ -2699,6 +2701,8 @@ static void i915_hangcheck_elapsed(struct work_struct *work)
int i;
int busy_count = 0, rings_hung = 0;
bool stuck[I915_NUM_RINGS] = { 0 };
+ u64 rnd = 0;
+
#define BUSY 1
#define KICK 5
#define HUNG 20
@@ -2715,6 +2719,8 @@ static void i915_hangcheck_elapsed(struct work_struct *work)
seqno = ring->get_seqno(ring, false);
acthd = intel_ring_get_active_head(ring);
+
+ rnd += acthd;
if (ring->hangcheck.seqno == seqno) {
if (ring_idle(ring)) {
@@ -2800,6 +2806,8 @@ static void i915_hangcheck_elapsed(struct work_struct *work)
if (rings_hung)
return i915_handle_error(dev, true, "Ring hung");
+ i915_check_scratch_page(dev_priv, rnd);
+
if (busy_count)
/* Reset timer case chip hangs without another request
* being added */