Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: 5590af3e115a ("drm/i915: Drive request submission through fence callbacks")
Fixes: 23902e49c999 ("drm/i915: Split request submit/execute phase into two")
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Joonas 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 48bc2a4a427ad81578f887d71d45794619a77211)
Signed-off-by: Jani Nikula <jani.nikula@intel.com>

authored by

Chris Wilson and committed by
Jani Nikula
0e932c08 b9f16ff2

+32 -7
+27 -7
drivers/gpu/drm/i915/i915_gem_request.c
··· 200 200 struct i915_gem_active *active, *next; 201 201 202 202 lockdep_assert_held(&request->i915->drm.struct_mutex); 203 - GEM_BUG_ON(!i915_sw_fence_done(&request->submit)); 204 - GEM_BUG_ON(!i915_sw_fence_done(&request->execute)); 203 + GEM_BUG_ON(!i915_sw_fence_signaled(&request->submit)); 204 + GEM_BUG_ON(!i915_sw_fence_signaled(&request->execute)); 205 205 GEM_BUG_ON(!i915_gem_request_completed(request)); 206 206 GEM_BUG_ON(!request->i915->gt.active_requests); 207 207 ··· 445 445 static int __i915_sw_fence_call 446 446 submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) 447 447 { 448 - if (state == FENCE_COMPLETE) { 449 - struct drm_i915_gem_request *request = 450 - container_of(fence, typeof(*request), submit); 448 + struct drm_i915_gem_request *request = 449 + container_of(fence, typeof(*request), submit); 451 450 451 + switch (state) { 452 + case FENCE_COMPLETE: 452 453 request->engine->submit_request(request); 454 + break; 455 + 456 + case FENCE_FREE: 457 + i915_gem_request_put(request); 458 + break; 453 459 } 454 460 455 461 return NOTIFY_DONE; ··· 464 458 static int __i915_sw_fence_call 465 459 execute_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) 466 460 { 461 + struct drm_i915_gem_request *request = 462 + container_of(fence, typeof(*request), execute); 463 + 464 + switch (state) { 465 + case FENCE_COMPLETE: 466 + break; 467 + 468 + case FENCE_FREE: 469 + i915_gem_request_put(request); 470 + break; 471 + } 472 + 467 473 return NOTIFY_DONE; 468 474 } 469 475 ··· 563 545 req->timeline->fence_context, 564 546 __timeline_get_seqno(req->timeline->common)); 565 547 566 - i915_sw_fence_init(&req->submit, submit_notify); 567 - i915_sw_fence_init(&req->execute, execute_notify); 548 + /* We bump the ref for the fence chain */ 549 + i915_sw_fence_init(&i915_gem_request_get(req)->submit, submit_notify); 550 + i915_sw_fence_init(&i915_gem_request_get(req)->execute, execute_notify); 551 + 568 552 /* Ensure that the execute fence completes after the submit fence - 569 553 * as we complete the execute fence from within the submit fence 570 554 * callback, its completion would otherwise be visible first.
+5
drivers/gpu/drm/i915/i915_sw_fence.h
··· 75 75 unsigned long timeout, 76 76 gfp_t gfp); 77 77 78 + static inline bool i915_sw_fence_signaled(const struct i915_sw_fence *fence) 79 + { 80 + return atomic_read(&fence->pending) <= 0; 81 + } 82 + 78 83 static inline bool i915_sw_fence_done(const struct i915_sw_fence *fence) 79 84 { 80 85 return atomic_read(&fence->pending) < 0;