diff options
author | Mika Kuoppala <mika.kuoppala@intel.com> | 2015-06-26 12:19:22 +0300 |
---|---|---|
committer | Mika Kuoppala <mika.kuoppala@intel.com> | 2015-06-26 17:47:46 +0300 |
commit | 123ec8cc620c915cda4fe04dfb233c544a7872c1 (patch) | |
tree | beff1ebcfbb77d366bfac07e99e833228aaa85da | |
parent | fd98d79140c39f3e4234f38c535213f3e757c38f (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.c | 51 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_gtt.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 8 |
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 */ |