static void hang_fini(struct hang *h) { *h->batch = MI_BATCH_BUFFER_END; i915_gem_chipset_flush(h->i915); i915_gem_object_unpin_map(h->obj); i915_gem_object_put(h->obj); i915_gem_object_unpin_map(h->hws); i915_gem_object_put(h->hws); kernel_context_close(h->ctx); igt_flush_test(h->i915, I915_WAIT_LOCKED); }
static int igt_hang_sanitycheck(void *arg) { struct drm_i915_private *i915 = arg; struct i915_request *rq; struct intel_engine_cs *engine; enum intel_engine_id id; struct hang h; int err; /* Basic check that we can execute our hanging batch */ mutex_lock(&i915->drm.struct_mutex); err = hang_init(&h, i915); if (err) goto unlock; for_each_engine(engine, i915, id) { struct igt_wedge_me w; long timeout; if (!intel_engine_can_store_dword(engine)) continue; rq = hang_create_request(&h, engine); if (IS_ERR(rq)) { err = PTR_ERR(rq); pr_err("Failed to create request for %s, err=%d\n", engine->name, err); goto fini; } i915_request_get(rq); *h.batch = MI_BATCH_BUFFER_END; i915_gem_chipset_flush(i915); i915_request_add(rq); timeout = 0; igt_wedge_on_timeout(&w, i915, HZ / 10 /* 100ms timeout*/) timeout = i915_request_wait(rq, I915_WAIT_LOCKED, MAX_SCHEDULE_TIMEOUT); if (i915_terminally_wedged(&i915->gpu_error)) timeout = -EIO; i915_request_put(rq); if (timeout < 0) { err = timeout; pr_err("Wait for request failed on %s, err=%d\n", engine->name, err); goto fini; } } fini: hang_fini(&h); unlock: mutex_unlock(&i915->drm.struct_mutex); return err; }
struct i915_request * igt_spinner_create_request(struct igt_spinner *spin, struct i915_gem_context *ctx, struct intel_engine_cs *engine, u32 arbitration_command) { struct i915_address_space *vm = &ctx->ppgtt->vm; struct i915_request *rq = NULL; struct i915_vma *hws, *vma; u32 *batch; int err; vma = i915_vma_instance(spin->obj, vm, NULL); if (IS_ERR(vma)) return ERR_CAST(vma); hws = i915_vma_instance(spin->hws, vm, NULL); if (IS_ERR(hws)) return ERR_CAST(hws); err = i915_vma_pin(vma, 0, 0, PIN_USER); if (err) return ERR_PTR(err); err = i915_vma_pin(hws, 0, 0, PIN_USER); if (err) goto unpin_vma; rq = i915_request_alloc(engine, ctx); if (IS_ERR(rq)) { err = PTR_ERR(rq); goto unpin_hws; } err = move_to_active(vma, rq, 0); if (err) goto cancel_rq; err = move_to_active(hws, rq, 0); if (err) goto cancel_rq; batch = spin->batch; *batch++ = MI_STORE_DWORD_IMM_GEN4; *batch++ = lower_32_bits(hws_address(hws, rq)); *batch++ = upper_32_bits(hws_address(hws, rq)); *batch++ = rq->fence.seqno; *batch++ = arbitration_command; *batch++ = MI_BATCH_BUFFER_START | 1 << 8 | 1; *batch++ = lower_32_bits(vma->node.start); *batch++ = upper_32_bits(vma->node.start); *batch++ = MI_BATCH_BUFFER_END; /* not reached */ i915_gem_chipset_flush(spin->i915); err = engine->emit_bb_start(rq, vma->node.start, PAGE_SIZE, 0); cancel_rq: if (err) { i915_request_skip(rq, err); i915_request_add(rq); } unpin_hws: i915_vma_unpin(hws); unpin_vma: i915_vma_unpin(vma); return err ? ERR_PTR(err) : rq; }
static int emit_recurse_batch(struct hang *h, struct i915_request *rq) { struct drm_i915_private *i915 = h->i915; struct i915_address_space *vm = rq->gem_context->ppgtt ? &rq->gem_context->ppgtt->vm : &i915->ggtt.vm; struct i915_vma *hws, *vma; unsigned int flags; u32 *batch; int err; vma = i915_vma_instance(h->obj, vm, NULL); if (IS_ERR(vma)) return PTR_ERR(vma); hws = i915_vma_instance(h->hws, vm, NULL); if (IS_ERR(hws)) return PTR_ERR(hws); err = i915_vma_pin(vma, 0, 0, PIN_USER); if (err) return err; err = i915_vma_pin(hws, 0, 0, PIN_USER); if (err) goto unpin_vma; err = i915_vma_move_to_active(vma, rq, 0); if (err) goto unpin_hws; if (!i915_gem_object_has_active_reference(vma->obj)) { i915_gem_object_get(vma->obj); i915_gem_object_set_active_reference(vma->obj); } err = i915_vma_move_to_active(hws, rq, 0); if (err) goto unpin_hws; if (!i915_gem_object_has_active_reference(hws->obj)) { i915_gem_object_get(hws->obj); i915_gem_object_set_active_reference(hws->obj); } batch = h->batch; if (INTEL_GEN(i915) >= 8) { *batch++ = MI_STORE_DWORD_IMM_GEN4; *batch++ = lower_32_bits(hws_address(hws, rq)); *batch++ = upper_32_bits(hws_address(hws, rq)); *batch++ = rq->fence.seqno; *batch++ = MI_ARB_CHECK; memset(batch, 0, 1024); batch += 1024 / sizeof(*batch); *batch++ = MI_ARB_CHECK; *batch++ = MI_BATCH_BUFFER_START | 1 << 8 | 1; *batch++ = lower_32_bits(vma->node.start); *batch++ = upper_32_bits(vma->node.start); } else if (INTEL_GEN(i915) >= 6) { *batch++ = MI_STORE_DWORD_IMM_GEN4; *batch++ = 0; *batch++ = lower_32_bits(hws_address(hws, rq)); *batch++ = rq->fence.seqno; *batch++ = MI_ARB_CHECK; memset(batch, 0, 1024); batch += 1024 / sizeof(*batch); *batch++ = MI_ARB_CHECK; *batch++ = MI_BATCH_BUFFER_START | 1 << 8; *batch++ = lower_32_bits(vma->node.start); } else if (INTEL_GEN(i915) >= 4) { *batch++ = MI_STORE_DWORD_IMM_GEN4 | MI_USE_GGTT; *batch++ = 0; *batch++ = lower_32_bits(hws_address(hws, rq)); *batch++ = rq->fence.seqno; *batch++ = MI_ARB_CHECK; memset(batch, 0, 1024); batch += 1024 / sizeof(*batch); *batch++ = MI_ARB_CHECK; *batch++ = MI_BATCH_BUFFER_START | 2 << 6; *batch++ = lower_32_bits(vma->node.start); } else { *batch++ = MI_STORE_DWORD_IMM | MI_MEM_VIRTUAL; *batch++ = lower_32_bits(hws_address(hws, rq)); *batch++ = rq->fence.seqno; *batch++ = MI_ARB_CHECK; memset(batch, 0, 1024); batch += 1024 / sizeof(*batch); *batch++ = MI_ARB_CHECK; *batch++ = MI_BATCH_BUFFER_START | 2 << 6; *batch++ = lower_32_bits(vma->node.start); } *batch++ = MI_BATCH_BUFFER_END; /* not reached */ i915_gem_chipset_flush(h->i915); flags = 0; if (INTEL_GEN(vm->i915) <= 5) flags |= I915_DISPATCH_SECURE; err = rq->engine->emit_bb_start(rq, vma->node.start, PAGE_SIZE, flags); unpin_hws: i915_vma_unpin(hws); unpin_vma: i915_vma_unpin(vma); return err; }
void igt_spinner_end(struct igt_spinner *spin) { *spin->batch = MI_BATCH_BUFFER_END; i915_gem_chipset_flush(spin->i915); }