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

drm/i915: Only prune fences after wait-for-all

Currently, we only allow ourselves to prune the fences so long as
all the waits completed (i.e. all the fences we checked were signaled),
and that the reservation snapshot did not change across the wait.
However, if we only waited for a subset of the reservation object, i.e.
just waiting for the last writer to complete as opposed to all readers
as well, then we would erroneously conclude we could prune the fences as
indeed although all of our waits were successful, they did not represent
the totality of the reservation object.

v2: We only need to check the shared fences due to construction (i.e.
all of the shared fences will be later than the exclusive fence, if
any).

Fixes: e54ca9774777 ("drm/i915: Remove completed fences after a wait")
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Matthew Auld <matthew.auld@intel.com>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180307171303.29466-1-chris@chris-wilson.co.uk
(cherry picked from commit fa73055b8442c97b3ba7cd0aa57cd2ad32124201)
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>

authored by

Chris Wilson and committed by
Rodrigo Vivi
82813ba9 e8cd7143

+12 -4
+12 -4
drivers/gpu/drm/i915/i915_gem.c
··· 434 434 dma_fence_put(shared[i]); 435 435 kfree(shared); 436 436 437 + /* 438 + * If both shared fences and an exclusive fence exist, 439 + * then by construction the shared fences must be later 440 + * than the exclusive fence. If we successfully wait for 441 + * all the shared fences, we know that the exclusive fence 442 + * must all be signaled. If all the shared fences are 443 + * signaled, we can prune the array and recover the 444 + * floating references on the fences/requests. 445 + */ 437 446 prune_fences = count && timeout >= 0; 438 447 } else { 439 448 excl = reservation_object_get_excl_rcu(resv); 440 449 } 441 450 442 - if (excl && timeout >= 0) { 451 + if (excl && timeout >= 0) 443 452 timeout = i915_gem_object_wait_fence(excl, flags, timeout, 444 453 rps_client); 445 - prune_fences = timeout >= 0; 446 - } 447 454 448 455 dma_fence_put(excl); 449 456 450 - /* Oportunistically prune the fences iff we know they have *all* been 457 + /* 458 + * Opportunistically prune the fences iff we know they have *all* been 451 459 * signaled and that the reservation object has not been changed (i.e. 452 460 * no new fences have been added). 453 461 */