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

Commit 0e932c08 authored by Chris Wilson's avatar Chris Wilson Committed by Jani Nikula
Browse files

drm/i915: Hold a reference on the request for its fence chain



Currently, we have an active reference for the request until it is
retired. Though it cannot be retired before it has been executed by
hardware, the request may be completed before we have finished
processing the execute fence, i.e. we may continue to process that fence
as we free the request.

Fixes: 5590af3e ("drm/i915: Drive request submission through fence callbacks")
Fixes: 23902e49 ("drm/i915: Split request submit/execute phase into two")
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20161125131718.20978-3-chris@chris-wilson.co.uk


(cherry picked from commit 48bc2a4a)
Signed-off-by: default avatarJani Nikula <jani.nikula@intel.com>
parent b9f16ff2
Loading
Loading
Loading
Loading
+27 −7
Original line number Original line Diff line number Diff line
@@ -200,8 +200,8 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request)
	struct i915_gem_active *active, *next;
	struct i915_gem_active *active, *next;


	lockdep_assert_held(&request->i915->drm.struct_mutex);
	lockdep_assert_held(&request->i915->drm.struct_mutex);
	GEM_BUG_ON(!i915_sw_fence_done(&request->submit));
	GEM_BUG_ON(!i915_sw_fence_signaled(&request->submit));
	GEM_BUG_ON(!i915_sw_fence_done(&request->execute));
	GEM_BUG_ON(!i915_sw_fence_signaled(&request->execute));
	GEM_BUG_ON(!i915_gem_request_completed(request));
	GEM_BUG_ON(!i915_gem_request_completed(request));
	GEM_BUG_ON(!request->i915->gt.active_requests);
	GEM_BUG_ON(!request->i915->gt.active_requests);


@@ -445,11 +445,17 @@ void i915_gem_request_submit(struct drm_i915_gem_request *request)
static int __i915_sw_fence_call
static int __i915_sw_fence_call
submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
{
{
	if (state == FENCE_COMPLETE) {
	struct drm_i915_gem_request *request =
	struct drm_i915_gem_request *request =
		container_of(fence, typeof(*request), submit);
		container_of(fence, typeof(*request), submit);


	switch (state) {
	case FENCE_COMPLETE:
		request->engine->submit_request(request);
		request->engine->submit_request(request);
		break;

	case FENCE_FREE:
		i915_gem_request_put(request);
		break;
	}
	}


	return NOTIFY_DONE;
	return NOTIFY_DONE;
@@ -458,6 +464,18 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
static int __i915_sw_fence_call
static int __i915_sw_fence_call
execute_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
execute_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state)
{
{
	struct drm_i915_gem_request *request =
		container_of(fence, typeof(*request), execute);

	switch (state) {
	case FENCE_COMPLETE:
		break;

	case FENCE_FREE:
		i915_gem_request_put(request);
		break;
	}

	return NOTIFY_DONE;
	return NOTIFY_DONE;
}
}


@@ -545,8 +563,10 @@ i915_gem_request_alloc(struct intel_engine_cs *engine,
		       req->timeline->fence_context,
		       req->timeline->fence_context,
		       __timeline_get_seqno(req->timeline->common));
		       __timeline_get_seqno(req->timeline->common));


	i915_sw_fence_init(&req->submit, submit_notify);
	/* We bump the ref for the fence chain */
	i915_sw_fence_init(&req->execute, execute_notify);
	i915_sw_fence_init(&i915_gem_request_get(req)->submit, submit_notify);
	i915_sw_fence_init(&i915_gem_request_get(req)->execute, execute_notify);

	/* Ensure that the execute fence completes after the submit fence -
	/* Ensure that the execute fence completes after the submit fence -
	 * as we complete the execute fence from within the submit fence
	 * as we complete the execute fence from within the submit fence
	 * callback, its completion would otherwise be visible first.
	 * callback, its completion would otherwise be visible first.
+5 −0
Original line number Original line Diff line number Diff line
@@ -75,6 +75,11 @@ int i915_sw_fence_await_reservation(struct i915_sw_fence *fence,
				    unsigned long timeout,
				    unsigned long timeout,
				    gfp_t gfp);
				    gfp_t gfp);


static inline bool i915_sw_fence_signaled(const struct i915_sw_fence *fence)
{
	return atomic_read(&fence->pending) <= 0;
}

static inline bool i915_sw_fence_done(const struct i915_sw_fence *fence)
static inline bool i915_sw_fence_done(const struct i915_sw_fence *fence)
{
{
	return atomic_read(&fence->pending) < 0;
	return atomic_read(&fence->pending) < 0;