aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_request.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2018-05-24 04:11:35 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2018-05-24 10:51:45 -0400
commit09a4c02e58c1b3d9748f78242962b7f63c68477e (patch)
tree95ae4c3efde90e325aaf7555f5bac77d8713be3f /drivers/gpu/drm/i915/i915_request.c
parent97c9de66ca8075871b31f4af05593e027e880e67 (diff)
drm/i915: Look for an active kernel context before switching
We were not very carefully checking to see if an older request on the engine was an earlier switch-to-kernel-context before deciding to emit a new switch. The end result would be that we could get into a permanent loop of trying to emit a new request to perform the switch simply to flush the existing switch. What we need is a means of tracking the completion of each timeline versus the kernel context, that is to detect if a more recent request has been submitted that would result in a switch away from the kernel context. To realise this, we need only to look in our syncmap on the kernel context and check that we have synchronized against all active rings. v2: Since all ringbuffer clients currently share the same timeline, we do have to use the gem_context to distinguish clients. As a bonus, include all the tracing used to debug the death inside suspend. v3: Test, test, test. Construct a selftest to exercise and assert the expected behaviour that multiple switch-to-contexts do not emit redundant requests. Reported-by: Mika Kuoppala <mika.kuoppala@intel.com> Fixes: a89d1f921c15 ("drm/i915: Split i915_gem_timeline into individual timelines") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Mika Kuoppala <mika.kuoppala@intel.com> Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20180524081135.15278-1-chris@chris-wilson.co.uk
Diffstat (limited to 'drivers/gpu/drm/i915/i915_request.c')
-rw-r--r--drivers/gpu/drm/i915/i915_request.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c
index fc499bcbd105..f187250e60c6 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -320,6 +320,7 @@ static void advance_ring(struct i915_request *request)
320 * is just about to be. Either works, if we miss the last two 320 * is just about to be. Either works, if we miss the last two
321 * noops - they are safe to be replayed on a reset. 321 * noops - they are safe to be replayed on a reset.
322 */ 322 */
323 GEM_TRACE("marking %s as inactive\n", ring->timeline->name);
323 tail = READ_ONCE(request->tail); 324 tail = READ_ONCE(request->tail);
324 list_del(&ring->active_link); 325 list_del(&ring->active_link);
325 } else { 326 } else {
@@ -1095,8 +1096,10 @@ void __i915_request_add(struct i915_request *request, bool flush_caches)
1095 i915_gem_active_set(&timeline->last_request, request); 1096 i915_gem_active_set(&timeline->last_request, request);
1096 1097
1097 list_add_tail(&request->ring_link, &ring->request_list); 1098 list_add_tail(&request->ring_link, &ring->request_list);
1098 if (list_is_first(&request->ring_link, &ring->request_list)) 1099 if (list_is_first(&request->ring_link, &ring->request_list)) {
1100 GEM_TRACE("marking %s as active\n", ring->timeline->name);
1099 list_add(&ring->active_link, &request->i915->gt.active_rings); 1101 list_add(&ring->active_link, &request->i915->gt.active_rings);
1102 }
1100 request->emitted_jiffies = jiffies; 1103 request->emitted_jiffies = jiffies;
1101 1104
1102 /* 1105 /*