diff options
Diffstat (limited to 'drivers/gpu/drm/i915/selftests/intel_lrc.c')
| -rw-r--r-- | drivers/gpu/drm/i915/selftests/intel_lrc.c | 129 | 
1 files changed, 127 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/selftests/intel_lrc.c b/drivers/gpu/drm/i915/selftests/intel_lrc.c index ea27c7cfbf96..582566faef09 100644 --- a/drivers/gpu/drm/i915/selftests/intel_lrc.c +++ b/drivers/gpu/drm/i915/selftests/intel_lrc.c @@ -104,13 +104,19 @@ static int emit_recurse_batch(struct spinner *spin,  	if (err)  		goto unpin_vma; -	i915_vma_move_to_active(vma, rq, 0); +	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);  	} -	i915_vma_move_to_active(hws, rq, 0); +	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); @@ -134,6 +140,7 @@ static int emit_recurse_batch(struct spinner *spin,  	err = rq->engine->emit_bb_start(rq, vma->node.start, PAGE_SIZE, 0); +unpin_hws:  	i915_vma_unpin(hws);  unpin_vma:  	i915_vma_unpin(vma); @@ -444,16 +451,134 @@ err_wedged:  	goto err_ctx_lo;  } +static int live_preempt_hang(void *arg) +{ +	struct drm_i915_private *i915 = arg; +	struct i915_gem_context *ctx_hi, *ctx_lo; +	struct spinner spin_hi, spin_lo; +	struct intel_engine_cs *engine; +	enum intel_engine_id id; +	int err = -ENOMEM; + +	if (!HAS_LOGICAL_RING_PREEMPTION(i915)) +		return 0; + +	if (!intel_has_reset_engine(i915)) +		return 0; + +	mutex_lock(&i915->drm.struct_mutex); + +	if (spinner_init(&spin_hi, i915)) +		goto err_unlock; + +	if (spinner_init(&spin_lo, i915)) +		goto err_spin_hi; + +	ctx_hi = kernel_context(i915); +	if (!ctx_hi) +		goto err_spin_lo; +	ctx_hi->sched.priority = I915_CONTEXT_MAX_USER_PRIORITY; + +	ctx_lo = kernel_context(i915); +	if (!ctx_lo) +		goto err_ctx_hi; +	ctx_lo->sched.priority = I915_CONTEXT_MIN_USER_PRIORITY; + +	for_each_engine(engine, i915, id) { +		struct i915_request *rq; + +		if (!intel_engine_has_preemption(engine)) +			continue; + +		rq = spinner_create_request(&spin_lo, ctx_lo, engine, +					    MI_ARB_CHECK); +		if (IS_ERR(rq)) { +			err = PTR_ERR(rq); +			goto err_ctx_lo; +		} + +		i915_request_add(rq); +		if (!wait_for_spinner(&spin_lo, rq)) { +			GEM_TRACE("lo spinner failed to start\n"); +			GEM_TRACE_DUMP(); +			i915_gem_set_wedged(i915); +			err = -EIO; +			goto err_ctx_lo; +		} + +		rq = spinner_create_request(&spin_hi, ctx_hi, engine, +					    MI_ARB_CHECK); +		if (IS_ERR(rq)) { +			spinner_end(&spin_lo); +			err = PTR_ERR(rq); +			goto err_ctx_lo; +		} + +		init_completion(&engine->execlists.preempt_hang.completion); +		engine->execlists.preempt_hang.inject_hang = true; + +		i915_request_add(rq); + +		if (!wait_for_completion_timeout(&engine->execlists.preempt_hang.completion, +						 HZ / 10)) { +			pr_err("Preemption did not occur within timeout!"); +			GEM_TRACE_DUMP(); +			i915_gem_set_wedged(i915); +			err = -EIO; +			goto err_ctx_lo; +		} + +		set_bit(I915_RESET_ENGINE + id, &i915->gpu_error.flags); +		i915_reset_engine(engine, NULL); +		clear_bit(I915_RESET_ENGINE + id, &i915->gpu_error.flags); + +		engine->execlists.preempt_hang.inject_hang = false; + +		if (!wait_for_spinner(&spin_hi, rq)) { +			GEM_TRACE("hi spinner failed to start\n"); +			GEM_TRACE_DUMP(); +			i915_gem_set_wedged(i915); +			err = -EIO; +			goto err_ctx_lo; +		} + +		spinner_end(&spin_hi); +		spinner_end(&spin_lo); +		if (igt_flush_test(i915, I915_WAIT_LOCKED)) { +			err = -EIO; +			goto err_ctx_lo; +		} +	} + +	err = 0; +err_ctx_lo: +	kernel_context_close(ctx_lo); +err_ctx_hi: +	kernel_context_close(ctx_hi); +err_spin_lo: +	spinner_fini(&spin_lo); +err_spin_hi: +	spinner_fini(&spin_hi); +err_unlock: +	igt_flush_test(i915, I915_WAIT_LOCKED); +	mutex_unlock(&i915->drm.struct_mutex); +	return err; +} +  int intel_execlists_live_selftests(struct drm_i915_private *i915)  {  	static const struct i915_subtest tests[] = {  		SUBTEST(live_sanitycheck),  		SUBTEST(live_preempt),  		SUBTEST(live_late_preempt), +		SUBTEST(live_preempt_hang),  	};  	if (!HAS_EXECLISTS(i915))  		return 0; +	if (i915_terminally_wedged(&i915->gpu_error)) +		return 0; +  	return i915_subtests(tests, i915);  }  | 

